<commit_before>/*
Language: Fortran
Author: Anthony Scemama <scemama@irsamc.ups-tlse.fr>
Category: scientific
*/

function(hljs) {
  var PARAMS = {
    className: 'params',
    begin: '\\(', end: '\\)'
  };

  var F_KEYWORDS = {
    constant: '.False. .True.',
    type: 'integer real character complex logical dimension allocatable|10 parameter ' +
      'external implicit|10 none double precision assign intent optional pointer ' +
      'target in out common equivalence data',
    keyword: 'kind do while private call intrinsic where elsewhere ' +
      'type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then ' +
      'public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. ' +
      'goto save else use module select case ' +
      'access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit ' +
      'continue format pause cycle exit ' +
      'c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg ' +
      'synchronous nopass non_overridable pass protected volatile abstract extends import ' +
      'non_intrinsic value deferred generic final enumerator class associate bind enum ' +
      'c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t ' +
      'c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double ' +
      'c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr ' +
      'c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer ' +
      'c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor ' +
      'numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ' +
      'ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous ' +
      'pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure',
    built_in: 'alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint ' +
      'dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl ' +
      'algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama ' +
      'iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod ' +
      'qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log ' +
      'log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate ' +
      'adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product ' +
      'eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul ' +
      'maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product ' +
      'radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind ' +
      'set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer ' +
      'dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ' +
      'ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode ' +
      'is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_of'  +
      'acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 ' +
      'atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits ' +
      'bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr ' +
      'num_images parity popcnt poppar shifta shiftl shiftr this_image'
  };
  return {
    case_insensitive: true,
    aliases: ['f90', 'f95'],
    keywords: F_KEYWORDS,
    contains: [
      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'string', relevance: 0}),
      hljs.inherit(hljs.QUOTE_STRING_MODE,{className: 'string', relevance: 0}),
      {
        className: 'function',
        beginKeywords: 'subroutine function program',
        illegal: '[${=\\n]',
        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]
      },
      hljs.COMMENT('!', '$', {relevance: 0}),
      {
        className: 'number',
        begin: '(?=\\b|\\+|\\-|\\.)(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*)(?:[de][+-]?\\d+)?\\b\\.?',
        relevance: 0
      }
    ]
  };
}<commit_msg>Updated fortran.js to new class names.<commit_after>/*
Language: Fortran
Author: Anthony Scemama <scemama@irsamc.ups-tlse.fr>
Category: scientific
*/

function(hljs) {
  var PARAMS = {
    className: 'params',
    begin: '\\(', end: '\\)'
  };

  var F_KEYWORDS = {
    literal: '.False. .True.',
    type: 'integer real character complex logical dimension allocatable|10 parameter ' +
      'external implicit|10 none double precision assign intent optional pointer ' +
      'target in out common equivalence data',
    keyword: 'kind do while private call intrinsic where elsewhere ' +
      'type endtype endmodule endselect endinterface end enddo endif if forall endforall only contains default return stop then ' +
      'public subroutine|10 function program .and. .or. .not. .le. .eq. .ge. .gt. .lt. ' +
      'goto save else use module select case ' +
      'access blank direct exist file fmt form formatted iostat name named nextrec number opened rec recl sequential status unformatted unit ' +
      'continue format pause cycle exit ' +
      'c_null_char c_alert c_backspace c_form_feed flush wait decimal round iomsg ' +
      'synchronous nopass non_overridable pass protected volatile abstract extends import ' +
      'non_intrinsic value deferred generic final enumerator class associate bind enum ' +
      'c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t ' +
      'c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double ' +
      'c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr ' +
      'c_new_line c_carriage_return c_horizontal_tab c_vertical_tab iso_c_binding c_loc c_funloc c_associated  c_f_pointer ' +
      'c_ptr c_funptr iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor ' +
      'numeric_storage_size output_unit c_f_procpointer ieee_arithmetic ieee_support_underflow_control ' +
      'ieee_get_underflow_mode ieee_set_underflow_mode newunit contiguous ' +
      'pad position action delim readwrite eor advance nml interface procedure namelist include sequence elemental pure',
    built_in: 'alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint ' +
      'dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl ' +
      'algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama ' +
      'iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod ' +
      'qnint qsign qsin qsinh qsqrt qtan qtanh abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log ' +
      'log10 max min nint sign sin sinh sqrt tan tanh print write dim lge lgt lle llt mod nullify allocate deallocate ' +
      'adjustl adjustr all allocated any associated bit_size btest ceiling count cshift date_and_time digits dot_product ' +
      'eoshift epsilon exponent floor fraction huge iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul ' +
      'maxexponent maxloc maxval merge minexponent minloc minval modulo mvbits nearest pack present product ' +
      'radix random_number random_seed range repeat reshape rrspacing scale scan selected_int_kind selected_real_kind ' +
      'set_exponent shape size spacing spread sum system_clock tiny transpose trim ubound unpack verify achar iachar transfer ' +
      'dble entry dprod cpu_time command_argument_count get_command get_command_argument get_environment_variable is_iostat_end ' +
      'ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode ' +
      'is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_of'  +
      'acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2 ' +
      'atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits ' +
      'bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr ' +
      'num_images parity popcnt poppar shifta shiftl shiftr this_image'
  };
  return {
    case_insensitive: true,
    aliases: ['f90', 'f95'],
    keywords: F_KEYWORDS,
    contains: [
      hljs.inherit(hljs.APOS_STRING_MODE, {className: 'string', relevance: 0}),
      hljs.inherit(hljs.QUOTE_STRING_MODE,{className: 'string', relevance: 0}),
      {
        className: 'function',
        beginKeywords: 'subroutine function program',
        illegal: '[${=\\n]',
        contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS]
      },
      hljs.COMMENT('!', '$', {relevance: 0}),
      {
        className: 'number',
        begin: '(?=\\b|\\+|\\-|\\.)(?=\\.\\d|\\d)(?:\\d+)?(?:\\.?\\d*)(?:[de][+-]?\\d+)?\\b\\.?',
        relevance: 0
      }
    ]
  };
}
<|endoftext|>


<commit_before>// Line rendering style

import {Style} from '../style';
import {StyleParser} from '../style_parser';
import {StyleManager} from '../style_manager';
import gl from '../../gl/constants'; // web workers don't have access to GL context, so import all GL constants
import Texture from '../../gl/texture';
import VertexLayout from '../../gl/vertex_layout';
import {buildPolylines} from '../../builders/polylines';
import renderDashArray from './dasharray';
import Geo from '../../geo';
import {shaderSrc_polygonsVertex, shaderSrc_polygonsFragment} from '../polygons/polygons';

export var Lines = Object.create(Style);

Object.assign(Lines, {
    name: 'lines',
    built_in: true,
    vertex_shader_src: shaderSrc_polygonsVertex,
    fragment_shader_src: shaderSrc_polygonsFragment,
    selection: true, // turn feature selection on

    init() {
        Style.init.apply(this, arguments);

        // Basic attributes, others can be added (see texture UVs below)
        var attribs = [
            { name: 'a_position', size: 4, type: gl.SHORT, normalized: false },
            { name: 'a_extrude', size: 4, type: gl.SHORT, normalized: false },
            { name: 'a_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true }
        ];

        // Tell the shader we want a order in vertex attributes, and to extrude lines
        this.defines.TANGRAM_LAYER_ORDER = true;
        this.defines.TANGRAM_EXTRUDE_LINES = true;

        // Optional feature selection
        if (this.selection) {
            attribs.push({ name: 'a_selection_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true });
        }

        // Optional line texture or dash array
        // (latter will be rendered at compile-time, when GL context available)
        if (this.texture || this.dash) {
            this.texcoords = true;
        }

        // Optional texture UVs
        if (this.texcoords) {
            this.defines.TANGRAM_TEXTURE_COORDS = true;

            // Scaling factor to add precision to line texture V coordinate packed as normalized short
            this.defines.TANGRAM_V_SCALE_ADJUST = Geo.tile_scale;

            // Add vertex attribute for UVs only when needed
            attribs.push({ name: 'a_texcoord', size: 2, type: gl.UNSIGNED_SHORT, normalized: true });
        }

        this.vertex_layout = new VertexLayout(attribs);

        // Additional single-allocated object used for holding outline style as it is processed
        // Separate from this.feature_style so that outline properties do not overwrite calculated
        // inline properties (outline call is made *within* the inline call)
        this.outline_feature_style = {};
        this.inline_feature_style = this.feature_style; // save reference to main computed style object
    },

    // Override
    compile () {
        this.parseLineTexture();
        return Style.compile.apply(this, arguments);
    },

    // Optionally apply a dash array pattern to this line
    parseLineTexture () {
        // Specify a line pattern
        if (this.dash) {
            // Optional background color for dash pattern (defaults transparent)
            if (this.dash_background_color) {
                this.dash_background_color = StyleParser.parseColor(this.dash_background_color).map(c => c * 255);
                this.dash_background_color[3] = 0; // alpha value is used to test if pixel is dash or space
            }

            // Render line pattern
            let dash = renderDashArray(this.dash, { background_color: this.dash_background_color });
            this.texture = '_' + this.name + '_dasharray';
            Texture.create(this.gl, this.texture, {
                data: dash.pixels,
                height: dash.length,
                width: 1,
                filtering: 'nearest'
            });

            this.defines.TANGRAM_LINE_BACKGROUND_COLOR = (this.dash_background_color != null);
        }

        // Specify a line texture (either directly, or rendered dash pattern from above)
        if (this.texture) {
            this.defines.TANGRAM_LINE_TEXTURE = true;
            this.defines.TANGRAM_ALPHA_TEST = 0.5; // pixels below this threshold are transparent
            this.shaders.uniforms = this.shaders.uniforms || {};
            this.shaders.uniforms.u_texture = this.texture;
            this.shaders.uniforms.u_texture_ratio = 1;

            // update line pattern aspect ratio after texture loads
            Texture.getInfo(this.texture).then(texture => {
                if (texture) {
                    this.shaders.uniforms.u_texture_ratio = texture.height / texture.width;
                }
            });
        }
    },

    // Calculate width at zoom given in `context`
    calcWidth (width, context) {
        return (width && StyleParser.cacheDistance(width, context)) || 0;
    },

    // Calculate width at next zoom (used for line width interpolation)
    calcWidthNextZoom (width, context) {
        context.zoom++;
        let val = this.calcWidth(width, context);
        context.zoom--;
        return val;
    },

    _parseFeature (feature, rule_style, context) {
        var style = this.feature_style;

        // line width in meters
        let width = this.calcWidth(rule_style.width, context);
        if (width < 0) {
            return; // skip lines with negative width
        }
        let next_width = this.calcWidthNextZoom(rule_style.next_width, context);

        if ((width === 0 && next_width === 0) || next_width < 0) {
            return; // skip lines that don't interpolate to a positive value at next zoom
        }

        // convert to units and relative change from previous zoom
        // NB: multiply by 2 because a given width is twice as big in screen space at the next zoom
        style.width = width * context.units_per_meter_overzoom;
        style.next_width = (next_width * 2) - width;
        style.next_width *= context.units_per_meter_overzoom;
        style.next_width /= 2; // NB: divide by 2 because extrusion width is halved in builder - remove?

        style.color = this.parseColor(rule_style.color, context);
        if (!style.color) {
            return;
        }

        // height defaults to feature height, but extrude style can dynamically adjust height by returning a number or array (instead of a boolean)
        style.z = (rule_style.z && StyleParser.cacheDistance(rule_style.z || 0, context)) || StyleParser.defaults.z;
        style.height = feature.properties.height || StyleParser.defaults.height;
        style.extrude = StyleParser.evalProp(rule_style.extrude, context);
        if (style.extrude) {
            if (typeof style.extrude === 'number') {
                style.height = style.extrude;
            }
            else if (Array.isArray(style.extrude)) {
                style.height = style.extrude[1];
            }
        }

        // Raise line height if extruded
        if (style.extrude && style.height) {
            style.z += style.height;
        }

        style.cap = rule_style.cap;
        style.join = rule_style.join;
        style.miter_limit = rule_style.miter_limit;
        style.tile_edges = rule_style.tile_edges; // usually activated for debugging, or rare visualization needs

        // Construct an outline style
        // Reusable outline style object, marked as already wrapped in cache objects (preprocessed = true)
        style.outline = style.outline || { width: {}, next_width: {}, preprocessed: true };

        if (rule_style.outline && rule_style.outline.color && rule_style.outline.width) {
            // outline width in meters
            // NB: multiply by 2 because outline is applied on both sides of line
            let outline_width = this.calcWidth(rule_style.outline.width, context) * 2;
            let outline_next_width = this.calcWidthNextZoom(rule_style.outline.next_width, context) * 2;

            if ((outline_width === 0 && outline_next_width === 0) || outline_width < 0 || outline_next_width < 0) {
                // skip lines that don't interpolate between zero or greater width
                style.outline.width.value = null;
                style.outline.next_width.value = null;
                style.outline.color = null;
            }
            else {
                // Maintain consistent outline width around the line fill
                style.outline.width.value = outline_width + width;
                style.outline.next_width.value = outline_next_width + next_width;

                style.outline.color = rule_style.outline.color;
                style.outline.cap = rule_style.outline.cap || rule_style.cap;
                style.outline.join = rule_style.outline.join || rule_style.join;
                style.outline.miter_limit = rule_style.outline.miter_limit || rule_style.miter_limit;
                style.outline.style = rule_style.outline.style || this.name;

                // Explicitly defined outline order, or inherited from inner line
                if (rule_style.outline.order) {
                    style.outline.order = this.parseOrder(rule_style.outline.order, context);
                }
                else {
                    style.outline.order = style.order;
                }

                // Don't let outline be above inner line
                if (style.outline.order > style.order) {
                    style.outline.order = style.order;
                }

                // Outlines are always at half-layer intervals to avoid conflicting with inner lines
                style.outline.order -= 0.5;
            }
        }
        else {
            style.outline.width.value = null;
            style.outline.next_width.value = null;
            style.outline.color = null;
        }

        return style;
    },

    _preprocess (draw) {
        draw.color = StyleParser.colorCacheObject(draw.color);
        draw.width = StyleParser.cacheObject(draw.width, StyleParser.cacheUnits);
        draw.next_width = StyleParser.cacheObject(draw.width, StyleParser.cacheUnits); // width will be computed for next zoom
        draw.z = StyleParser.cacheObject(draw.z, StyleParser.cacheUnits);

        if (draw.outline) {
            draw.outline.color = StyleParser.colorCacheObject(draw.outline.color);
            draw.outline.width = StyleParser.cacheObject(draw.outline.width, StyleParser.cacheUnits);
            draw.outline.next_width = StyleParser.cacheObject(draw.outline.width, StyleParser.cacheUnits); // width re-computed for next zoom
        }
        return draw;
    },

    /**
     * A "template" that sets constant attibutes for each vertex, which is then modified per vertex or per feature.
     * A plain JS array matching the order of the vertex layout.
     */
    makeVertexTemplate(style) {
        let i = 0;

        // position - x & y coords will be filled in per-vertex below
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = style.z || 0;

        // layer order - w coord of 'position' attribute (for packing efficiency)
        this.vertex_template[i++] = this.scaleOrder(style.order);

        // extrusion vector
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;

        // scaling to previous and next zoom
        this.vertex_template[i++] = style.next_width;

        // color
        this.vertex_template[i++] = style.color[0] * 255;
        this.vertex_template[i++] = style.color[1] * 255;
        this.vertex_template[i++] = style.color[2] * 255;
        this.vertex_template[i++] = style.color[3] * 255;

        // selection color
        if (this.selection) {
            this.vertex_template[i++] = style.selection_color[0] * 255;
            this.vertex_template[i++] = style.selection_color[1] * 255;
            this.vertex_template[i++] = style.selection_color[2] * 255;
            this.vertex_template[i++] = style.selection_color[3] * 255;
        }

        // Add texture UVs to template only if needed
        if (this.texcoords) {
            this.vertex_template[i++] = 0;
            this.vertex_template[i++] = 0;
        }

        return this.vertex_template;
    },

    buildLines(lines, style, vertex_data, context, options) {
        // Outline (build first so that blended geometry without a depth test is drawn first/under the inner line)
        this.feature_style = this.outline_feature_style; // swap in outline-specific style holder
        if (style.outline && style.outline.color != null && style.outline.width.value != null) {
            var outline_style = StyleManager.styles[style.outline.style];
            if (outline_style) {
                outline_style.addFeature(context.feature, style.outline, context);
            }
        }

        // Main line
        this.feature_style = this.inline_feature_style; // restore calculated style for inline
        let vertex_template = this.makeVertexTemplate(style);
        buildPolylines(
            lines,
            style.width,
            vertex_data,
            vertex_template,
            {
                cap: style.cap,
                join: style.join,
                miter_limit: style.miter_limit,
                scaling_index: this.vertex_layout.index.a_extrude,
                scaling_normalize: 256, // values have an 8-bit fraction
                texcoord_index: this.vertex_layout.index.a_texcoord,
                texcoord_width: (style.width || style.next_width) / context.tile.overzoom2, // UVs can't calc for zero-width, use next zoom width in that case
                texcoord_normalize: 65535, // scale UVs to unsigned shorts
                closed_polygon: options && options.closed_polygon,
                remove_tile_edges: !style.tile_edges && options && options.remove_tile_edges,
                tile_edge_tolerance: Geo.tile_scale * context.tile.pad_scale * 4
            }
        );
    },

    buildPolygons(polygons, style, vertex_data, context) {
        // Render polygons as individual lines
        for (let p=0; p < polygons.length; p++) {
            this.buildLines(polygons[p], style, vertex_data, context, { closed_polygon: true, remove_tile_edges: true });
        }
    }

});
<commit_msg>lines: set dash background color flag when parsing<commit_after>// Line rendering style

import {Style} from '../style';
import {StyleParser} from '../style_parser';
import {StyleManager} from '../style_manager';
import gl from '../../gl/constants'; // web workers don't have access to GL context, so import all GL constants
import Texture from '../../gl/texture';
import VertexLayout from '../../gl/vertex_layout';
import {buildPolylines} from '../../builders/polylines';
import renderDashArray from './dasharray';
import Geo from '../../geo';
import {shaderSrc_polygonsVertex, shaderSrc_polygonsFragment} from '../polygons/polygons';

export var Lines = Object.create(Style);

Object.assign(Lines, {
    name: 'lines',
    built_in: true,
    vertex_shader_src: shaderSrc_polygonsVertex,
    fragment_shader_src: shaderSrc_polygonsFragment,
    selection: true, // turn feature selection on

    init() {
        Style.init.apply(this, arguments);

        // Basic attributes, others can be added (see texture UVs below)
        var attribs = [
            { name: 'a_position', size: 4, type: gl.SHORT, normalized: false },
            { name: 'a_extrude', size: 4, type: gl.SHORT, normalized: false },
            { name: 'a_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true }
        ];

        // Tell the shader we want a order in vertex attributes, and to extrude lines
        this.defines.TANGRAM_LAYER_ORDER = true;
        this.defines.TANGRAM_EXTRUDE_LINES = true;

        // Optional feature selection
        if (this.selection) {
            attribs.push({ name: 'a_selection_color', size: 4, type: gl.UNSIGNED_BYTE, normalized: true });
        }

        // Optional line texture or dash array
        // (latter will be rendered at compile-time, when GL context available)
        if (this.texture || this.dash) {
            this.texcoords = true;
        }

        // Optional texture UVs
        if (this.texcoords) {
            this.defines.TANGRAM_TEXTURE_COORDS = true;

            // Scaling factor to add precision to line texture V coordinate packed as normalized short
            this.defines.TANGRAM_V_SCALE_ADJUST = Geo.tile_scale;

            // Add vertex attribute for UVs only when needed
            attribs.push({ name: 'a_texcoord', size: 2, type: gl.UNSIGNED_SHORT, normalized: true });
        }

        this.vertex_layout = new VertexLayout(attribs);

        // Additional single-allocated object used for holding outline style as it is processed
        // Separate from this.feature_style so that outline properties do not overwrite calculated
        // inline properties (outline call is made *within* the inline call)
        this.outline_feature_style = {};
        this.inline_feature_style = this.feature_style; // save reference to main computed style object
    },

    // Override
    compile () {
        this.parseLineTexture();
        return Style.compile.apply(this, arguments);
    },

    // Optionally apply a dash array pattern to this line
    parseLineTexture () {
        // Specify a line pattern
        if (this.dash) {
            // Optional background color for dash pattern (defaults transparent)
            if (this.dash_background_color) {
                this.dash_background_color = StyleParser.parseColor(this.dash_background_color).map(c => c * 255);
                this.dash_background_color[3] = 0; // alpha value is used to test if pixel is dash or space
                this.defines.TANGRAM_LINE_BACKGROUND_COLOR = true;
            }

            // Render line pattern
            let dash = renderDashArray(this.dash, { background_color: this.dash_background_color });
            this.texture = '_' + this.name + '_dasharray';
            Texture.create(this.gl, this.texture, {
                data: dash.pixels,
                height: dash.length,
                width: 1,
                filtering: 'nearest'
            });
        }

        // Specify a line texture (either directly, or rendered dash pattern from above)
        if (this.texture) {
            this.defines.TANGRAM_LINE_TEXTURE = true;
            this.defines.TANGRAM_ALPHA_TEST = 0.5; // pixels below this threshold are transparent
            this.shaders.uniforms = this.shaders.uniforms || {};
            this.shaders.uniforms.u_texture = this.texture;
            this.shaders.uniforms.u_texture_ratio = 1;

            // update line pattern aspect ratio after texture loads
            Texture.getInfo(this.texture).then(texture => {
                if (texture) {
                    this.shaders.uniforms.u_texture_ratio = texture.height / texture.width;
                }
            });
        }
    },

    // Calculate width at zoom given in `context`
    calcWidth (width, context) {
        return (width && StyleParser.cacheDistance(width, context)) || 0;
    },

    // Calculate width at next zoom (used for line width interpolation)
    calcWidthNextZoom (width, context) {
        context.zoom++;
        let val = this.calcWidth(width, context);
        context.zoom--;
        return val;
    },

    _parseFeature (feature, rule_style, context) {
        var style = this.feature_style;

        // line width in meters
        let width = this.calcWidth(rule_style.width, context);
        if (width < 0) {
            return; // skip lines with negative width
        }
        let next_width = this.calcWidthNextZoom(rule_style.next_width, context);

        if ((width === 0 && next_width === 0) || next_width < 0) {
            return; // skip lines that don't interpolate to a positive value at next zoom
        }

        // convert to units and relative change from previous zoom
        // NB: multiply by 2 because a given width is twice as big in screen space at the next zoom
        style.width = width * context.units_per_meter_overzoom;
        style.next_width = (next_width * 2) - width;
        style.next_width *= context.units_per_meter_overzoom;
        style.next_width /= 2; // NB: divide by 2 because extrusion width is halved in builder - remove?

        style.color = this.parseColor(rule_style.color, context);
        if (!style.color) {
            return;
        }

        // height defaults to feature height, but extrude style can dynamically adjust height by returning a number or array (instead of a boolean)
        style.z = (rule_style.z && StyleParser.cacheDistance(rule_style.z || 0, context)) || StyleParser.defaults.z;
        style.height = feature.properties.height || StyleParser.defaults.height;
        style.extrude = StyleParser.evalProp(rule_style.extrude, context);
        if (style.extrude) {
            if (typeof style.extrude === 'number') {
                style.height = style.extrude;
            }
            else if (Array.isArray(style.extrude)) {
                style.height = style.extrude[1];
            }
        }

        // Raise line height if extruded
        if (style.extrude && style.height) {
            style.z += style.height;
        }

        style.cap = rule_style.cap;
        style.join = rule_style.join;
        style.miter_limit = rule_style.miter_limit;
        style.tile_edges = rule_style.tile_edges; // usually activated for debugging, or rare visualization needs

        // Construct an outline style
        // Reusable outline style object, marked as already wrapped in cache objects (preprocessed = true)
        style.outline = style.outline || { width: {}, next_width: {}, preprocessed: true };

        if (rule_style.outline && rule_style.outline.color && rule_style.outline.width) {
            // outline width in meters
            // NB: multiply by 2 because outline is applied on both sides of line
            let outline_width = this.calcWidth(rule_style.outline.width, context) * 2;
            let outline_next_width = this.calcWidthNextZoom(rule_style.outline.next_width, context) * 2;

            if ((outline_width === 0 && outline_next_width === 0) || outline_width < 0 || outline_next_width < 0) {
                // skip lines that don't interpolate between zero or greater width
                style.outline.width.value = null;
                style.outline.next_width.value = null;
                style.outline.color = null;
            }
            else {
                // Maintain consistent outline width around the line fill
                style.outline.width.value = outline_width + width;
                style.outline.next_width.value = outline_next_width + next_width;

                style.outline.color = rule_style.outline.color;
                style.outline.cap = rule_style.outline.cap || rule_style.cap;
                style.outline.join = rule_style.outline.join || rule_style.join;
                style.outline.miter_limit = rule_style.outline.miter_limit || rule_style.miter_limit;
                style.outline.style = rule_style.outline.style || this.name;

                // Explicitly defined outline order, or inherited from inner line
                if (rule_style.outline.order) {
                    style.outline.order = this.parseOrder(rule_style.outline.order, context);
                }
                else {
                    style.outline.order = style.order;
                }

                // Don't let outline be above inner line
                if (style.outline.order > style.order) {
                    style.outline.order = style.order;
                }

                // Outlines are always at half-layer intervals to avoid conflicting with inner lines
                style.outline.order -= 0.5;
            }
        }
        else {
            style.outline.width.value = null;
            style.outline.next_width.value = null;
            style.outline.color = null;
        }

        return style;
    },

    _preprocess (draw) {
        draw.color = StyleParser.colorCacheObject(draw.color);
        draw.width = StyleParser.cacheObject(draw.width, StyleParser.cacheUnits);
        draw.next_width = StyleParser.cacheObject(draw.width, StyleParser.cacheUnits); // width will be computed for next zoom
        draw.z = StyleParser.cacheObject(draw.z, StyleParser.cacheUnits);

        if (draw.outline) {
            draw.outline.color = StyleParser.colorCacheObject(draw.outline.color);
            draw.outline.width = StyleParser.cacheObject(draw.outline.width, StyleParser.cacheUnits);
            draw.outline.next_width = StyleParser.cacheObject(draw.outline.width, StyleParser.cacheUnits); // width re-computed for next zoom
        }
        return draw;
    },

    /**
     * A "template" that sets constant attibutes for each vertex, which is then modified per vertex or per feature.
     * A plain JS array matching the order of the vertex layout.
     */
    makeVertexTemplate(style) {
        let i = 0;

        // position - x & y coords will be filled in per-vertex below
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = style.z || 0;

        // layer order - w coord of 'position' attribute (for packing efficiency)
        this.vertex_template[i++] = this.scaleOrder(style.order);

        // extrusion vector
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;
        this.vertex_template[i++] = 0;

        // scaling to previous and next zoom
        this.vertex_template[i++] = style.next_width;

        // color
        this.vertex_template[i++] = style.color[0] * 255;
        this.vertex_template[i++] = style.color[1] * 255;
        this.vertex_template[i++] = style.color[2] * 255;
        this.vertex_template[i++] = style.color[3] * 255;

        // selection color
        if (this.selection) {
            this.vertex_template[i++] = style.selection_color[0] * 255;
            this.vertex_template[i++] = style.selection_color[1] * 255;
            this.vertex_template[i++] = style.selection_color[2] * 255;
            this.vertex_template[i++] = style.selection_color[3] * 255;
        }

        // Add texture UVs to template only if needed
        if (this.texcoords) {
            this.vertex_template[i++] = 0;
            this.vertex_template[i++] = 0;
        }

        return this.vertex_template;
    },

    buildLines(lines, style, vertex_data, context, options) {
        // Outline (build first so that blended geometry without a depth test is drawn first/under the inner line)
        this.feature_style = this.outline_feature_style; // swap in outline-specific style holder
        if (style.outline && style.outline.color != null && style.outline.width.value != null) {
            var outline_style = StyleManager.styles[style.outline.style];
            if (outline_style) {
                outline_style.addFeature(context.feature, style.outline, context);
            }
        }

        // Main line
        this.feature_style = this.inline_feature_style; // restore calculated style for inline
        let vertex_template = this.makeVertexTemplate(style);
        buildPolylines(
            lines,
            style.width,
            vertex_data,
            vertex_template,
            {
                cap: style.cap,
                join: style.join,
                miter_limit: style.miter_limit,
                scaling_index: this.vertex_layout.index.a_extrude,
                scaling_normalize: 256, // values have an 8-bit fraction
                texcoord_index: this.vertex_layout.index.a_texcoord,
                texcoord_width: (style.width || style.next_width) / context.tile.overzoom2, // UVs can't calc for zero-width, use next zoom width in that case
                texcoord_normalize: 65535, // scale UVs to unsigned shorts
                closed_polygon: options && options.closed_polygon,
                remove_tile_edges: !style.tile_edges && options && options.remove_tile_edges,
                tile_edge_tolerance: Geo.tile_scale * context.tile.pad_scale * 4
            }
        );
    },

    buildPolygons(polygons, style, vertex_data, context) {
        // Render polygons as individual lines
        for (let p=0; p < polygons.length; p++) {
            this.buildLines(polygons[p], style, vertex_data, context, { closed_polygon: true, remove_tile_edges: true });
        }
    }

});
<|endoftext|>


<commit_before>'use strict'

var async = require('async');

function saveAttendance(args, callback) {
  var seneca = this;
  var ENTITY_NS = 'cd/attendance';

  var attendance = args.attendance;
  var attendanceEntity = seneca.make$(ENTITY_NS);

  async.series([
    checkForExistingAttendanceRecord,
    saveAttendanceRecord
  ], function (err, res) {
    if(err) return callback(null, {error: err});
    return callback(null, res);
  });

  function checkForExistingAttendanceRecord(done) {
    attendanceEntity.list$({userId: attendance.user_id, eventId: attendance.event_id, eventDate: attendance.event_date}, function (err, response) {
      if(err) return done(err);
      if(response.length > 0) return done(new Error('Attendance record already exists'));
      return done();
    });
  }

  function saveAttendanceRecord(done) {
    attendanceEntity.save$(attendance, function (err, response) {
      if(err) return done(err);
      return done(null, response);
    });
  }

}

module.exports = saveAttendance;<commit_msg>allow existing attendance records to be updated<commit_after>'use strict'

var async = require('async');

function saveAttendance(args, callback) {
  var seneca = this;
  var ENTITY_NS = 'cd/attendance';
  var attendance = args.attendance;
  var attendanceEntity = seneca.make$(ENTITY_NS);

  async.series([
    checkForExistingAttendanceRecord,
    saveAttendanceRecord
  ], function (err, res) {
    if(err) return callback(null, {error: err});
    return callback(null, res);
  });

  function checkForExistingAttendanceRecord(done) {
    if(attendance.id) return done();
    attendanceEntity.list$({userId: attendance.user_id, eventId: attendance.event_id, eventDate: attendance.event_date}, function (err, response) {
      if(err) return done(err);
      if(response.length > 0) return done(new Error('Attendance record already exists'));
      return done();
    });
  }

  function saveAttendanceRecord(done) {
    attendanceEntity.save$(attendance, function (err, response) {
      if(err) return done(err);
      return done(null, response);
    });
  }

}

module.exports = saveAttendance;<|endoftext|>


<commit_before>export const imageComposer = (article) => {
  let image
  let heroImage = article.heroImage[0]
  let facebookImage = article.ogImage[0]

  if (heroImage) {
    return {
      desktopImage: heroImage.image.resizedTargets.desktop.url,
      mobileImage: heroImage.image.resizedTargets.mobile.url
    }
  }

  let source
  if (image) {
    const regex = /.+~(.+)/
    source = image.match(regex)
    source = source ? source[1] : ''
  }

  let imageSet = {}
  if (facebookImage) {
    imageSet = {
      desktopImage: facebookImage.image.resizedTargets.desktop.url,
      mobileImage: facebookImage.image.resizedTargets.mobile.url
    }
  } else {
    // display logo when the image is empty
    image = '/asset/review.png'
    imageSet = {
      desktopImage: image,
      mobileImage: image
    }
  }

  return imageSet
}
<commit_msg>resolved the image in Home<commit_after>export const imageComposer = (article) => {
  let image
  let heroImage = article.heroImage
  let facebookImage = article.ogImage

  if (heroImage.image) {
    return {
      desktopImage: heroImage.image.resizedTargets.desktop.url,
      mobileImage: heroImage.image.resizedTargets.mobile.url
    }
  }

  let source
  if (image) {
    const regex = /.+~(.+)/
    source = image.match(regex)
    source = source ? source[1] : ''
  }

  let imageSet = {}
  if (facebookImage.image) {
    imageSet = {
      desktopImage: facebookImage.image.resizedTargets.desktop.url,
      mobileImage: facebookImage.image.resizedTargets.mobile.url
    }
  } else {
    // display logo when the image is empty
    image = '/asset/review.png'
    imageSet = {
      desktopImage: image,
      mobileImage: image
    }
  }

  return imageSet
}
<|endoftext|>


<commit_before>// ==UserScript==
// @include http://*/*
// @include https://*/*
// @exclude http://*.reddit.com/*
// @exclude https://*.reddit.com/*
// ==/UserScript==

/*
 * THIS FILE IS NOT A USERSCRIPT. DO NOT ATTEMPT TO INSTALL IT AS SUCH.
 *
 * The above header is used by Opera.
 */

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

"use strict";

// Embed JS files, for Opera
/*$(EMOTE_MAP)*/
/*$(SR_DATA)*/
/*$(SCRIPT_COMMON)*/

function endsWith(text, s) {
    // FIXME this sucks
    var f = text.lastIndexOf(s);
    if(f > -1) {
        return f + s.length == text.length;
    } else {
        return false;
    }
}

// As a note, this regexp is a little forgiving in some respects and strict in
// others. It will not permit text in the [] portion, but alt-text quotes don't
// have to match each other.
//
// Flags are parsed, but ignored in code. This isn't for any technical reason-
// I'm just making the assumption that more specialized syntaxes will generally
// stay in Reddit.
//
//                           <  emote  ><  flags   >   <    alt-text     >
var emote_regexp = /\[\s*\]\((\/[\w!:]+)(?:[\w!\-]*)\s*(?:["']([^"]*)["'])?\)/g;

var tag_blacklist = {
    // Meta tags that we should never touch
    "HTML": 1, "HEAD": 1, "TITLE": 1, "BASE": 1, "LINK": 1, "META": 1, "STYLE": 1, "SCRIPT": 1,
    // Some random things I'm a little worried about
    "SVG": 1, "MATH": 1
};

function process(prefs, sr_array, root) {
    // Opera does not seem to expose NodeFilter to content scripts, so we
    // cannot specify NodeFilter.SHOW_TEXT. Its value is defined to be 4 in the
    // DOM spec, though, so that works.
    //
    // Opera also throws an error if we do not specify all four arguments,
    // though Firefox and Chrome will accept just the first two.
    var walker = document.createTreeWalker(root, /*NodeFilter.SHOW_TEXT*/ 4, undefined, undefined);
    var node;
    // TreeWalker's seem to stop returning nodes if you delete a node while
    // iterating over it.
    var deletion_list = [];

    while((node = walker.nextNode()) !== null) {
        var parent = node.parentNode;

        if(!tag_blacklist[parent.tagName]) {
            emote_regexp.lastIndex = 0;

            var parts = [];
            var end_of_prev = 0; // End index of previous emote match
            var match;

            while((match = emote_regexp.exec(node.data)) !== null) {
                // Check that emote exists
                if(!emote_map[match[1]]) {
                    continue;
                }

                var emote_info = emote_map[match[1]];
                var is_nsfw = emote_info[0];
                var source_id = emote_info[1];

                // Check that it hasn't been disabled somehow
                if(!sr_array[source_id] || (is_nsfw && !prefs.enableNSFW)) {
                    continue;
                }

                // Keep text between the last emote and this one (or the start
                // of the text element)
                var before_text = node.data.slice(end_of_prev, match.index);
                if(before_text) {
                    parts.push(document.createTextNode(before_text));
                }

                // Build emote
                var emote_element = document.createElement("span");
                emote_element.className = "bpmote-" + sanitize(match[1].slice(1));
                if(match[2] !== undefined) {
                    // Alt text. (Quotes aren't captured by the regexp)
                    emote_element.title = match[2];
                }
                parts.push(emote_element);

                // Next text element will start after this emote
                end_of_prev = match.index + match[0].length;
            }

            // If length == 0, then there were no emote matches to begin with,
            // and we should just leave it alone
            if(parts.length) {
                // There were emotes, so grab the last bit of text at the end
                var before_text = node.data.slice(end_of_prev);
                if(before_text) {
                    parts.push(document.createTextNode(before_text));
                }

                // Insert all our new nodes
                for(var i = 0; i < parts.length; i++) {
                    parent.insertBefore(parts[i], node);
                }

                // Remove original text node
                deletion_list.push(node);
            }
        }
    }

    for(var i = 0; i < deletion_list.length; i++) {
        var node = deletion_list[i];
        node.parentNode.removeChild(node);
    }
}

function run(prefs) {
    if(!prefs.enableGlobalEmotes) {
        return;
    }

    var sr_array = make_sr_array(prefs);
    process(prefs, sr_array, document.body);

    switch(platform) {
        case "chrome":
        case "firefox":
            var observer = new MutationSummary({
                callback: function(summaries) {
                    var elements = summaries[0].added;
                    for(var i = 0; i < elements.length; i++) {
                        process(prefs, sr_array, elements[i]);
                    }
                },
                queries: [
                    {element: "*"} // All elements (since any of them can contain text)
                ]});
            break;

        case "opera":
        default:
            document.body.addEventListener("DOMNodeInserted", function(event) {
                var element = event.target;
                process(prefs, sr_array, elements[i]);
            }, false);
            break;
    }
}

// Manual whitelisting on Firefox, because we can't exclude URL's
if(!endsWith(document.location.hostname, "reddit.com")) {
    // Only apply a subset of CSS globally. We don't need bpmotes.css, extracss,
    // or combiners nonsense as we ignore all flags and have no real "custom" stuff.
    // Does nothing on Firefox.
    apply_css("/emote-classes.css");

    // This script is generally run before the DOM is built. Opera may break
    // that rule, but I don't know how and there's nothing we can do anyway.
    window.addEventListener("DOMContentLoaded", function() {
        get_prefs(run);
    }, false);
}
<commit_msg>Moved CSS application in BGM<commit_after>// ==UserScript==
// @include http://*/*
// @include https://*/*
// @exclude http://*.reddit.com/*
// @exclude https://*.reddit.com/*
// ==/UserScript==

/*
 * THIS FILE IS NOT A USERSCRIPT. DO NOT ATTEMPT TO INSTALL IT AS SUCH.
 *
 * The above header is used by Opera.
 */

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

"use strict";

// Embed JS files, for Opera
/*$(EMOTE_MAP)*/
/*$(SR_DATA)*/
/*$(SCRIPT_COMMON)*/

function endsWith(text, s) {
    // FIXME this sucks
    var f = text.lastIndexOf(s);
    if(f > -1) {
        return f + s.length == text.length;
    } else {
        return false;
    }
}

// As a note, this regexp is a little forgiving in some respects and strict in
// others. It will not permit text in the [] portion, but alt-text quotes don't
// have to match each other.
//
// Flags are parsed, but ignored in code. This isn't for any technical reason-
// I'm just making the assumption that more specialized syntaxes will generally
// stay in Reddit.
//
//                           <  emote  ><  flags   >   <    alt-text     >
var emote_regexp = /\[\s*\]\((\/[\w!:]+)(?:[\w!\-]*)\s*(?:["']([^"]*)["'])?\)/g;

var tag_blacklist = {
    // Meta tags that we should never touch
    "HTML": 1, "HEAD": 1, "TITLE": 1, "BASE": 1, "LINK": 1, "META": 1, "STYLE": 1, "SCRIPT": 1,
    // Some random things I'm a little worried about
    "SVG": 1, "MATH": 1
};

function process(prefs, sr_array, root) {
    // Opera does not seem to expose NodeFilter to content scripts, so we
    // cannot specify NodeFilter.SHOW_TEXT. Its value is defined to be 4 in the
    // DOM spec, though, so that works.
    //
    // Opera also throws an error if we do not specify all four arguments,
    // though Firefox and Chrome will accept just the first two.
    var walker = document.createTreeWalker(root, /*NodeFilter.SHOW_TEXT*/ 4, undefined, undefined);
    var node;
    // TreeWalker's seem to stop returning nodes if you delete a node while
    // iterating over it.
    var deletion_list = [];

    while((node = walker.nextNode()) !== null) {
        var parent = node.parentNode;

        if(!tag_blacklist[parent.tagName]) {
            emote_regexp.lastIndex = 0;

            var parts = [];
            var end_of_prev = 0; // End index of previous emote match
            var match;

            while((match = emote_regexp.exec(node.data)) !== null) {
                // Check that emote exists
                if(!emote_map[match[1]]) {
                    continue;
                }

                var emote_info = emote_map[match[1]];
                var is_nsfw = emote_info[0];
                var source_id = emote_info[1];

                // Check that it hasn't been disabled somehow
                if(!sr_array[source_id] || (is_nsfw && !prefs.enableNSFW)) {
                    continue;
                }

                // Keep text between the last emote and this one (or the start
                // of the text element)
                var before_text = node.data.slice(end_of_prev, match.index);
                if(before_text) {
                    parts.push(document.createTextNode(before_text));
                }

                // Build emote
                var emote_element = document.createElement("span");
                emote_element.className = "bpmote-" + sanitize(match[1].slice(1));
                if(match[2] !== undefined) {
                    // Alt text. (Quotes aren't captured by the regexp)
                    emote_element.title = match[2];
                }
                parts.push(emote_element);

                // Next text element will start after this emote
                end_of_prev = match.index + match[0].length;
            }

            // If length == 0, then there were no emote matches to begin with,
            // and we should just leave it alone
            if(parts.length) {
                // There were emotes, so grab the last bit of text at the end
                var before_text = node.data.slice(end_of_prev);
                if(before_text) {
                    parts.push(document.createTextNode(before_text));
                }

                // Insert all our new nodes
                for(var i = 0; i < parts.length; i++) {
                    parent.insertBefore(parts[i], node);
                }

                // Remove original text node
                deletion_list.push(node);
            }
        }
    }

    for(var i = 0; i < deletion_list.length; i++) {
        var node = deletion_list[i];
        node.parentNode.removeChild(node);
    }
}

function run(prefs) {
    if(!prefs.enableGlobalEmotes) {
        return;
    }

    // Only apply a subset of CSS globally. We don't need bpmotes.css, extracss,
    // or combiners nonsense as we ignore all flags and have no real "custom" stuff.
    //
    // We run this here, instead of down in the main bit, to avoid applying large
    // chunks of CSS when this script is disabled.
    //
    // Does nothing on Firefox.
    apply_css("/emote-classes.css");

    var sr_array = make_sr_array(prefs);
    process(prefs, sr_array, document.body);

    switch(platform) {
        case "chrome":
        case "firefox":
            var observer = new MutationSummary({
                callback: function(summaries) {
                    var elements = summaries[0].added;
                    for(var i = 0; i < elements.length; i++) {
                        process(prefs, sr_array, elements[i]);
                    }
                },
                queries: [
                    {element: "*"} // All elements (since any of them can contain text)
                ]});
            break;

        case "opera":
        default:
            document.body.addEventListener("DOMNodeInserted", function(event) {
                var element = event.target;
                process(prefs, sr_array, elements[i]);
            }, false);
            break;
    }
}

// Manual whitelisting on Firefox, because we can't exclude URL's
if(!endsWith(document.location.hostname, "reddit.com")) {
    // This script is generally run before the DOM is built. Opera may break
    // that rule, but I don't know how and there's nothing we can do anyway.
    window.addEventListener("DOMContentLoaded", function() {
        get_prefs(run);
    }, false);
}
<|endoftext|>


<commit_before>const questions = require('./questions');
const yo = require('yo-yo');

var Game = function() {

	this.step = 0;
	this.score = 0;
	this.duration = 30000;

	this.init = () => {
		setTimeout(() => {
			this.question();
			this.timer();

		}, 3000);
	}

	this.question = () => {

		let questionText = yo`<a-entity material="color: white" text="text: '${questions[this.step].question}'; size: 0.24"></a-entity>`
		$('question').append(questionText)

		for (let i = 0; i < questions[this.step].choices.length; i++) {
			this.choice(questions[this.step].choices[i]);
    	}

	}

	this.choice = (choice) => {

		let delay = 500
		let position = this.position();
		let rotation = this.rotation(position);
		let scene = document.querySelector('#elements');

		let entity = yo`
			<a-entity flapping>
				<a-entity clicked obj-model="obj: #fly-a-obj; mtl: #fly-a-mtl" data-choice="${choice}" position="${position.x} ${position.y} ${position.z}" scale="0 0 0" rotation="${rotation.x} ${rotation.y} ${rotation.z}" sound="src: #sound-eat; on: click">
				<a-animation attribute="scale" dur="200" fill="forwards" to="1 1 1" repeat="0"></a-animation>
				<a-entity data-choice="${choice}" material="color: white" text="text: ${choice}; size: 0.24" position="-0.2 0.1 0"></a-entity>
				<a-box data-choice="${choice}" cursor-listener opacity="0"></a-box>
			</a-entity>

			<a-entity clicked obj-model="obj: #fly-b-obj; mtl: #fly-b-mtl" data-choice="${choice}" position="${position.x} ${position.y} ${position.z}" scale="0 0 0" rotation="${rotation.x} ${rotation.y} ${rotation.z}" sound="src: #sound-eat; on: click">
				<a-animation attribute="scale" dur="200" fill="forwards" to="1 1 1" repeat="0"></a-animation>
				<a-entity data-choice="${choice}" material="color: white" text="text: ${choice}; size: 0.24" position="-0.2 0.1 0"></a-entity>
				<a-box data-choice="${choice}" cursor-listener opacity="0"></a-box>
				</a-entity>
			</a-entity>`;

			setTimeout(function() {
				scene.appendChild(entity)
			}, delay);

			delay = delay + 500
	}

	// Sets Timer
	this.timer = () => {

		let timer = yo`<a-box timer color="tomato" data-duration="${this.duration}" position="0 1 -1.5" depth="0.05" height="0.1" width="2"></a-box>`;
		let scene = document.querySelector('#scene');
		scene.appendChild(timer);

		setTimeout(function() {

			this.result();
		}, this.duration + 2000);
	}

	this.result = () => {

	}

	this.answer = (value) => {
		console.log(91919191, value)
		if(questions[this.step].answer === value) {
			this.score = this.score++
		}
		this.step++

		// wipe existing answers && load new answers
		this.refresh()
	}

	this.refresh = () => {
	  let delay = 200
		$('#elements').children('').each(function () {
			setTimeout(() => $(this).remove(), delay);
			delay = delay + 200;
		});
		setTimeout(() => this.question(), delay);
	}

	this.position = () => {

		let position = {
			x: this.getRand(-10, 10),
			y: this.getRand(1, 3),
			z: this.getRand(-2, -12),
		}

		return position;
	}

	this.rotation = (position) => {

		let rotation = {
			x: this.getRand(-5, 5),
			y: position.x * -8,
			z: this.getRand(-5, 5),
		}

		return rotation;
	}

	this.getRand = (min, max) => {
    	return Math.round(Math.random() * (max - min) + min);
	}
}

module.exports = Game
<commit_msg>update timer timeout<commit_after>const questions = require('./questions');
const yo = require('yo-yo');

var Game = function() {

	this.step = 0;
	this.score = 0;
	this.duration = 30000;

	this.init = () => {
		setTimeout(() => {
			this.question();
			this.timer();

		}, 3000);
	}

	this.question = () => {

		let question
		let questionText = yo`<a-entity position="1 2 -5" material="color: white" text="text: '${questions[this.step].question}'; size: 0.24"></a-entity>`

		$('#question').append(questionText)

		for (let i = 0; i < questions[this.step].choices.length; i++) {
			this.choice(questions[this.step].choices[i]);
    	}

	}

	this.choice = (choice) => {

		let delay = 500
		let position = this.position();
		let rotation = this.rotation(position);
		let scene = document.querySelector('#elements');

		let entity = yo`
			<a-entity flapping>
				<a-entity clicked obj-model="obj: #fly-a-obj; mtl: #fly-a-mtl" data-choice="${choice}" position="${position.x} ${position.y} ${position.z}" scale="0 0 0" rotation="${rotation.x} ${rotation.y} ${rotation.z}" sound="src: #sound-eat; on: click">
				<a-animation attribute="scale" dur="200" fill="forwards" to="1 1 1" repeat="0"></a-animation>
				<a-entity data-choice="${choice}" material="color: white" text="text: ${choice}; size: 0.24" position="-0.2 0.1 0"></a-entity>
				<a-box data-choice="${choice}" cursor-listener opacity="0"></a-box>
			</a-entity>

			<a-entity clicked obj-model="obj: #fly-b-obj; mtl: #fly-b-mtl" data-choice="${choice}" position="${position.x} ${position.y} ${position.z}" scale="0 0 0" rotation="${rotation.x} ${rotation.y} ${rotation.z}" sound="src: #sound-eat; on: click">
				<a-animation attribute="scale" dur="200" fill="forwards" to="1 1 1" repeat="0"></a-animation>
				<a-entity data-choice="${choice}" material="color: white" text="text: ${choice}; size: 0.24" position="-0.2 0.1 0"></a-entity>
				<a-box data-choice="${choice}" cursor-listener opacity="0"></a-box>
				</a-entity>
			</a-entity>`;

			setTimeout(function() {
				scene.appendChild(entity)
			}, delay);

			delay = delay + 500
	}

	// Sets Timer
	this.timer = () => {

		let timer = yo`<a-box timer color="tomato" data-duration="${this.duration}" position="0 1 -1.5" depth="0.05" height="0.1" width="2"></a-box>`;
		let scene = document.querySelector('#scene');
		scene.appendChild(timer);

		setTimeout(this.result, this.duration + 2000);
	}

	this.result = () => {

		console.log("End of the game!");
	}

	this.answer = (value) => {
		console.log(91919191, value)
		if(questions[this.step].answer === value) {
			this.score = this.score++
		}
		this.step++

		// wipe existing answers && load new answers
		this.refresh()
	}

	this.refresh = () => {
	  let delay = 200
		$('#elements').children('').each(function () {
			setTimeout(() => $(this).remove(), delay);
			delay = delay + 200;
		});
		setTimeout(() => this.question(), delay);
	}

	this.position = () => {

		let position = {
			x: this.getRand(-10, 10),
			y: this.getRand(1, 3),
			z: this.getRand(-2, -12),
		}

		return position;
	}

	this.rotation = (position) => {

		let rotation = {
			x: this.getRand(-5, 5),
			y: position.x * -8,
			z: this.getRand(-5, 5),
		}

		return rotation;
	}

	this.getRand = (min, max) => {
    	return Math.round(Math.random() * (max - min) + min);
	}
}

module.exports = Game
<|endoftext|>


<commit_before>import ol from 'openlayers'
import {ProvideMapMixin} from './ProvideMapMixin'
import {mixin} from '../utilities'

/**
 * This Class is a Wrap around {ol.layer.Group} providing some extra functionality. This class is normally used for a
 * category of layers containing them.
 */
export class GroupLayer extends mixin(ol.layer.Group, ProvideMapMixin) {
  /**
   * @param {object} [options={}]
   */
  constructor (options = {}) {
    super(options)

    let listenerKeys = new WeakMap()

    this.getLayers().on('add', /** ol.CollectionEvent */ e => {
      let layer = e.element
      if (layer.provideMap) {
        layer.provideMap(this.getProvidedMap())
      }
      listenerKeys.set(layer, layer.on('change:visible', () => {
        this.dispatchEvent({
          type: 'change:childVisible',
          child: layer
        })
      }))
    })

    this.getLayers().on('remove', /** ol.CollectionEvent */ e => {
      let layer = e.element
      if (layer.provideMap) {
        layer.provideMap(null)
      }
      ol.Observable.unByKey(listenerKeys.get(layer))
      listenerKeys.delete(layer)
    })
  }

  /**
   * The provideMap methods of all contained children are called recursively
   * @param {G4UMap} map
   */
  provideMap (map) {
    super.provideMap(map)

    this.getLayers().forEach(layer => {
      if (layer.provideMap) { layer.provideMap(map) }
    })
  }

  /**
   * calls callback for every terminal, non-group Layer
   * @param {Function} callback
   */
  recursiveForEach (callback) {
    this.getLayers().forEach(layer => {
      callback(layer, this)
      if (layer.recursiveForEach) {
        layer.recursiveForEach(callback)
      }
    })
  }

  /**
   * Attachs a listener to each layer and to each newly added listener and removes the listener if the layer gets
   * removed.
   * @param eventType
   * @param listener
   */
  forEachOn (eventType, listener) {
    this.recursiveForEach(layer => {
      layer.on(eventType, listener)
      if (layer instanceof GroupLayer) {
        this.getLayers().on('add', (e) => {
          e.element.on(eventType, listener)
        })
        this.getLayers().on('remove', (e) => {
          e.element.un(eventType, listener)
        })
      }
    })
  }

  /**
   * Checks how many children are visible. Doesn't check visibility of the group layer
   * @returns {number}
   */
  countChildrenVisible () {
    let array = this.getLayersArray()
    let count = 0

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i] instanceof GroupLayer) {
        count += array[i].countChildrenVisible()
      } else if (array[i].getVisible()) {
        count += 1
      }
    }
    return count
  }

  countChildren () {
    let array = this.getLayersArray()
    let count = 0

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i] instanceof GroupLayer) {
        count += array[i].countChildren()
      } else {
        count += 1
      }
    }
    return count
  }

  /**
   * Returns the layers inside as an array.
   * @returns {ol.layer.Base[]}
   */
  getLayersArray () {
    return this.getLayers().getArray()
  }

  /**
   * Returns the number of direct child layers
   * @returns {number}
   */
  getLength () {
    return this.getLayers().getLength()
  }

  /**
   * checks if the given layer is a child of the grouplayer
   * @param {ol.layer.Base} layer
   * @returns {boolean}
   */
  isParentOf (layer) {
    let found = false
    this.recursiveForEach(function (childLayer) {
      if (layer === childLayer) {
        found = true
      }
    })
    return found
  }

  /**
   * Returns all ids of all contained layers and its own.
   * @returns {number[]}
   */
  getIds () {
    let ids = [this.get('id')]

    let array = this.getLayersArray()

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i].getIds) {
        ids = ids.concat(array[i].getIds())
      } else {
        ids.push(array[i].get('id'))
      }
    }

    return ids
  }

  /**
   * Returns all attributions of all visible layers.
   * @returns {number[]}
   */
  getAttributions () {
    let attributions = []

    this.recursiveForEach(function (layer) {
      if (layer.getVisible()) {
        if (layer.getSource) {
          let atts = layer.getSource().getAttributions()
          if (atts) {
            attributions = attributions.concat(atts)
          }
        }
      }
    })

    return attributions
  }

  /**
   * Remove layer by id
   * @param {string|number} id
   */
  removeLayerById (id) {
    let layers = this.getLayers()
    for (let i = 0; i < layers.getLength(); i++) {
      if (layers.item(i).get('id') === id) {
        return layers.removeAt(i)
      } else if (layers.item(i).removeLayerById) {
        let res = layers.item(i).removeLayerById(id)
        if (res) {
          return res
        }
      }
    }
  }

  /**
   * Get layer by id
   * @param {string|number} id
   */
  getLayerById (id) {
    let layers = this.getLayers()
    for (let i = 0; i < layers.getLength(); i++) {
      if (layers.item(i).get('id') === id) {
        return layers.item(i)
      } else if (layers.item(i).getLayerById) {
        let res = layers.item(i).getLayerById(id)
        if (res) {
          return res
        }
      }
    }
  }

  /**
   * removes layer
   * @param {ol.layer.Base} layer
   */
  removeLayer (layer) {
    let found = this.getLayers().remove(layer)
    if (!found) {
      this.getLayers().forEach(subLayer => {
        if (!found && subLayer.removeLayer) {
          found = subLayer.removeLayer(layer)
        }
      })
    }
    return found
  }

  /**
   * gives an object with ids as keys and visibility as value
   * @returns {Object.<string|number,boolean>}
   */
  getIdsVisibilities () {
    let visibilities = {}
    this.recursiveForEach(layer => {
      if (layer.get('id')) {
        visibilities[layer.get('id')] = layer.getVisible()
      }
    })
    return visibilities
  }

  /**
   * Sets the visibility of the layers to the given visibility
   * @param {Object.<string|number,boolean>} visibilities
   */
  setIdsVisibilities (visibilities) {
    this.recursiveForEach(layer => {
      if (layer.get('id')) {
        layer.setVisible(visibilities[layer.get('id')])
      }
    })
  }
}
<commit_msg>added containsLayer method<commit_after>import ol from 'openlayers'
import {ProvideMapMixin} from './ProvideMapMixin'
import {mixin} from '../utilities'

/**
 * This Class is a Wrap around {ol.layer.Group} providing some extra functionality. This class is normally used for a
 * category of layers containing them.
 */
export class GroupLayer extends mixin(ol.layer.Group, ProvideMapMixin) {
  /**
   * @param {object} [options={}]
   */
  constructor (options = {}) {
    super(options)

    let listenerKeys = new WeakMap()

    this.getLayers().on('add', /** ol.CollectionEvent */ e => {
      let layer = e.element
      if (layer.provideMap) {
        layer.provideMap(this.getProvidedMap())
      }
      listenerKeys.set(layer, layer.on('change:visible', () => {
        this.dispatchEvent({
          type: 'change:childVisible',
          child: layer
        })
      }))
    })

    this.getLayers().on('remove', /** ol.CollectionEvent */ e => {
      let layer = e.element
      if (layer.provideMap) {
        layer.provideMap(null)
      }
      ol.Observable.unByKey(listenerKeys.get(layer))
      listenerKeys.delete(layer)
    })
  }

  /**
   * The provideMap methods of all contained children are called recursively
   * @param {G4UMap} map
   */
  provideMap (map) {
    super.provideMap(map)

    this.getLayers().forEach(layer => {
      if (layer.provideMap) { layer.provideMap(map) }
    })
  }

  /**
   * calls callback for every terminal, non-group Layer
   * @param {Function} callback
   */
  recursiveForEach (callback) {
    this.getLayers().forEach(layer => {
      callback(layer, this)
      if (layer.recursiveForEach) {
        layer.recursiveForEach(callback)
      }
    })
  }

  /**
   * Attachs a listener to each layer and to each newly added listener and removes the listener if the layer gets
   * removed.
   * @param eventType
   * @param listener
   */
  forEachOn (eventType, listener) {
    this.recursiveForEach(layer => {
      layer.on(eventType, listener)
      if (layer instanceof GroupLayer) {
        this.getLayers().on('add', (e) => {
          e.element.on(eventType, listener)
        })
        this.getLayers().on('remove', (e) => {
          e.element.un(eventType, listener)
        })
      }
    })
  }

  /**
   * Checks how many children are visible. Doesn't check visibility of the group layer
   * @returns {number}
   */
  countChildrenVisible () {
    let array = this.getLayersArray()
    let count = 0

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i] instanceof GroupLayer) {
        count += array[i].countChildrenVisible()
      } else if (array[i].getVisible()) {
        count += 1
      }
    }
    return count
  }

  countChildren () {
    let array = this.getLayersArray()
    let count = 0

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i] instanceof GroupLayer) {
        count += array[i].countChildren()
      } else {
        count += 1
      }
    }
    return count
  }

  /**
   * Returns the layers inside as an array.
   * @returns {ol.layer.Base[]}
   */
  getLayersArray () {
    return this.getLayers().getArray()
  }

  /**
   * Returns the number of direct child layers
   * @returns {number}
   */
  getLength () {
    return this.getLayers().getLength()
  }

  /**
   * checks if the given layer is a child of the grouplayer
   * @param {ol.layer.Base} layer
   * @returns {boolean}
   */
  isParentOf (layer) {
    let found = false
    this.recursiveForEach(function (childLayer) {
      if (layer === childLayer) {
        found = true
      }
    })
    return found
  }

  /**
   * Returns all ids of all contained layers and its own.
   * @returns {number[]}
   */
  getIds () {
    let ids = [this.get('id')]

    let array = this.getLayersArray()

    for (let i = 0, ii = array.length; i < ii; i++) {
      if (array[i].getIds) {
        ids = ids.concat(array[i].getIds())
      } else {
        ids.push(array[i].get('id'))
      }
    }

    return ids
  }

  /**
   * Returns all attributions of all visible layers.
   * @returns {number[]}
   */
  getAttributions () {
    let attributions = []

    this.recursiveForEach(function (layer) {
      if (layer.getVisible()) {
        if (layer.getSource) {
          let atts = layer.getSource().getAttributions()
          if (atts) {
            attributions = attributions.concat(atts)
          }
        }
      }
    })

    return attributions
  }

  /**
   * Remove layer by id
   * @param {string|number} id
   */
  removeLayerById (id) {
    let layers = this.getLayers()
    for (let i = 0; i < layers.getLength(); i++) {
      if (layers.item(i).get('id') === id) {
        return layers.removeAt(i)
      } else if (layers.item(i).removeLayerById) {
        let res = layers.item(i).removeLayerById(id)
        if (res) {
          return res
        }
      }
    }
  }

  /**
   * Get layer by id
   * @param {string|number} id
   */
  getLayerById (id) {
    let layers = this.getLayers()
    for (let i = 0; i < layers.getLength(); i++) {
      if (layers.item(i).get('id') === id) {
        return layers.item(i)
      } else if (layers.item(i).getLayerById) {
        let res = layers.item(i).getLayerById(id)
        if (res) {
          return res
        }
      }
    }
  }

  /**
   * removes layer
   * @param {ol.layer.Base} layer
   */
  removeLayer (layer) {
    let found = this.getLayers().remove(layer)
    if (!found) {
      this.getLayers().forEach(subLayer => {
        if (!found && subLayer.removeLayer) {
          found = subLayer.removeLayer(layer)
        }
      })
    }
    return found
  }

  /**
   * gives an object with ids as keys and visibility as value
   * @returns {Object.<string|number,boolean>}
   */
  getIdsVisibilities () {
    let visibilities = {}
    this.recursiveForEach(layer => {
      if (layer.get('id')) {
        visibilities[layer.get('id')] = layer.getVisible()
      }
    })
    return visibilities
  }

  /**
   * Sets the visibility of the layers to the given visibility
   * @param {Object.<string|number,boolean>} visibilities
   */
  setIdsVisibilities (visibilities) {
    this.recursiveForEach(layer => {
      if (layer.get('id')) {
        layer.setVisible(visibilities[layer.get('id')])
      }
    })
  }

  /**
   * Checks if the group contains the layer
   * @param {ol.layer.Layer} layer
   * @returns {boolean}
   */
  containsLayer (layer) {
    return this.getLayers().getArray().some(subLayer => {
      if (subLayer === layer) {
        return true
      }
      if (subLayer.containsLayer) {
        return subLayer.containsLayer(layer)
      }
    })
  }
}
<|endoftext|>


<commit_before>function CircularBuffer(capacity){
    var readPoint = 0, writePoint = 0, buffer = new Array(capacity);

    return{
        read: function(){
            if(isBufferEmpty){
                throw new BufferEmptyException();
            }
            var data = buffer[readPoint];
            buffer[readPoint] = null;
            updateReadPoint();
            return data;
        },

        write: function(data){
            updateBuffer(data, function(){
                if(isBufferFull()){
                    throw new BufferFullException();
                }
                buffer[writePoint] = data;
            });
        },

        forceWrite: function(data){

        },

        clear: function(){

        },

        isFull:function(){

        },

        isEmpty:function(){

        }
    };

    function isBufferEmpty(){
        return buffer.every(isEmpty);
    }

    function isBufferFull(){
        return buffer.filter(isFull).length === capacity;
    }

    function updateReadPoint(){
        readPoint = (readPoint + 1) % capacity;
    }

    function updateWritePoint(){
        writePoint = (writePoint + 1) % capacity;
    }

    function updateBuffer(data, callback){
        if(isEmpty(data)){
            return;
        }
        callback();
        updateWritePoint();
    }

    function isFull(data){
        return !isEmpty(data);
    }

    function isEmpty(data){
        return data === null || data === undefined;
    }
};

function BufferEmptyException(){
    this.name ="BufferEmptyException";
    this.message = "Buffer is empty";
}

function BufferFullException(){
    this.name = "BufferFullException";
    this.message = "Buffer is Full";
}

module.exports = {
    circularBuffer: function(capacity){
        return new CircularBuffer(capacity);
    },

    bufferEmptyException: function(){
        return new BufferEmptyException();
    },

    bufferFullException: function(){
        return new BufferFullException();
    }
}<commit_msg>implement forceWrite, clear, isFull to buffer<commit_after>function CircularBuffer(capacity){
    var readPoint = 0, writePoint = 0, buffer = new Array(capacity);

    return{
        read: function(){
            if(isBufferEmpty){
                throw new BufferEmptyException();
            }
            var data = buffer[readPoint];
            buffer[readPoint] = null;
            updateReadPoint();
            return data;
        },

        write: function(data){
            updateBuffer(data, function(){
                if(isBufferFull()){
                    throw new BufferFullException();
                }
                buffer[writePoint] = data;
            });
        },

        forceWrite: function(data){
            updateBuffer(data, () => {
                if(isBufferFull()){
                    updateReadPoint();
                }
                buffer[writePoint] = data;
            })
        },

        clear: function(){
            readPoint = 0;
            writePoint = 0;
            buffer = new Array(capacity);
        },

        isFull:function(){
            return isBufferFull();
        },

        isEmpty:function(){
            return isBufferEmpty();
        }
    };

    function isBufferEmpty(){
        return buffer.every(isEmpty);
    }

    function isBufferFull(){
        return buffer.filter(isFull).length === capacity;
    }

    function updateReadPoint(){
        readPoint = (readPoint + 1) % capacity;
    }

    function updateWritePoint(){
        writePoint = (writePoint + 1) % capacity;
    }

    function updateBuffer(data, callback){
        if(isEmpty(data)){
            return;
        }
        callback();
        updateWritePoint();
    }

    function isFull(data){
        return !isEmpty(data);
    }

    function isEmpty(data){
        return data === null || data === undefined;
    }
};

function BufferEmptyException(){
    this.name ="BufferEmptyException";
    this.message = "Buffer is empty";
}

function BufferFullException(){
    this.name = "BufferFullException";
    this.message = "Buffer is Full";
}

module.exports = {
    circularBuffer: function(capacity){
        return new CircularBuffer(capacity);
    },

    bufferEmptyException: function(){
        return new BufferEmptyException();
    },

    bufferFullException: function(){
        return new BufferFullException();
    }
}<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var propertyMap = {
    "background": {"#$0": 1},
    "background-color": {"#$0": 1, "transparent": 1, "fixed": 1},
    "background-image": {"url('/$0')": 1},
    "background-repeat": {"repeat": 1, "repeat-x": 1, "repeat-y": 1, "no-repeat": 1, "inherit": 1},
    "background-position": {"bottom":2, "center":2, "left":2, "right":2, "top":2, "inherit":2},
    "background-attachment": {"scroll": 1, "fixed": 1},
    "background-size": {"cover": 1, "contain": 1},
    "background-clip": {"border-box": 1, "padding-box": 1, "content-box": 1},
    "background-origin": {"border-box": 1, "padding-box": 1, "content-box": 1},
    "border": {"solid $0": 1, "dashed $0": 1, "dotted $0": 1, "#$0": 1},
    "border-color": {"#$0": 1},
    "border-style": {"solid":2, "dashed":2, "dotted":2, "double":2, "groove":2, "hidden":2, "inherit":2, "inset":2, "none":2, "outset":2, "ridged":2},
    "border-collapse": {"collapse": 1, "separate": 1},
    "bottom": {"px": 1, "em": 1, "%": 1},
    "clear": {"left": 1, "right": 1, "both": 1, "none": 1},
    "color": {"#$0": 1, "rgb(#$00,0,0)": 1},
    "cursor": {"default": 1, "pointer": 1, "move": 1, "text": 1, "wait": 1, "help": 1, "progress": 1, "n-resize": 1, "ne-resize": 1, "e-resize": 1, "se-resize": 1, "s-resize": 1, "sw-resize": 1, "w-resize": 1, "nw-resize": 1},
    "display": {"none": 1, "block": 1, "inline": 1, "inline-block": 1, "table-cell": 1},
    "empty-cells": {"show": 1, "hide": 1},
    "float": {"left": 1, "right": 1, "none": 1},
    "font-family": {"Arial":2,"Comic Sans MS":2,"Consolas":2,"Courier New":2,"Courier":2,"Georgia":2,"Monospace":2,"Sans-Serif":2, "Segoe UI":2,"Tahoma":2,"Times New Roman":2,"Trebuchet MS":2,"Verdana": 1},
    "font-size": {"px": 1, "em": 1, "%": 1},
    "font-weight": {"bold": 1, "normal": 1},
    "font-style": {"italic": 1, "normal": 1},
    "font-variant": {"normal": 1, "small-caps": 1},
    "height": {"px": 1, "em": 1, "%": 1},
    "left": {"px": 1, "em": 1, "%": 1},
    "letter-spacing": {"normal": 1},
    "line-height": {"normal": 1},
    "list-style-type": {"none": 1, "disc": 1, "circle": 1, "square": 1, "decimal": 1, "decimal-leading-zero": 1, "lower-roman": 1, "upper-roman": 1, "lower-greek": 1, "lower-latin": 1, "upper-latin": 1, "georgian": 1, "lower-alpha": 1, "upper-alpha": 1},
    "margin": {"px": 1, "em": 1, "%": 1},
    "margin-right": {"px": 1, "em": 1, "%": 1},
    "margin-left": {"px": 1, "em": 1, "%": 1},
    "margin-top": {"px": 1, "em": 1, "%": 1},
    "margin-bottom": {"px": 1, "em": 1, "%": 1},
    "max-height": {"px": 1, "em": 1, "%": 1},
    "max-width": {"px": 1, "em": 1, "%": 1},
    "min-height": {"px": 1, "em": 1, "%": 1},
    "min-width": {"px": 1, "em": 1, "%": 1},
    "overflow": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "overflow-x": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "overflow-y": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "padding": {"px": 1, "em": 1, "%": 1},
    "padding-top": {"px": 1, "em": 1, "%": 1},
    "padding-right": {"px": 1, "em": 1, "%": 1},
    "padding-bottom": {"px": 1, "em": 1, "%": 1},
    "padding-left": {"px": 1, "em": 1, "%": 1},
    "page-break-after": {"auto": 1, "always": 1, "avoid": 1, "left": 1, "right": 1},
    "page-break-before": {"auto": 1, "always": 1, "avoid": 1, "left": 1, "right": 1},
    "position": {"absolute": 1, "relative": 1, "fixed": 1, "static": 1},
    "right": {"px": 1, "em": 1, "%": 1},
    "table-layout": {"fixed": 1, "auto": 1},
    "text-decoration": {"none": 1, "underline": 1, "line-through": 1, "blink": 1},
    "text-align": {"left": 1, "right": 1, "center": 1, "justify": 1},
    "text-transform": {"capitalize": 1, "uppercase": 1, "lowercase": 1, "none": 1},
    "top": {"px": 1, "em": 1, "%": 1},
    "vertical-align": {"top": 1, "bottom": 1},
    "visibility": {"hidden": 1, "visible": 1},
    "white-space": {"nowrap": 1, "normal": 1, "pre": 1, "pre-line": 1, "pre-wrap": 1},
    "width": {"px": 1, "em": 1, "%": 1},
    "word-spacing": {"normal": 1},

    // opacity
    "filter": {"alpha(opacity=$0100)": 1},

    "text-shadow": {"$02px 2px 2px #777": 1},
    "text-overflow": {"ellipsis-word": 1, "clip": 1, "ellipsis": 1},

    // border radius
    "-moz-border-radius": 1,
    "-moz-border-radius-topright": 1,
    "-moz-border-radius-bottomright": 1,
    "-moz-border-radius-topleft": 1,
    "-moz-border-radius-bottomleft": 1,
    "-webkit-border-radius": 1,
    "-webkit-border-top-right-radius": 1,
    "-webkit-border-top-left-radius": 1,
    "-webkit-border-bottom-right-radius": 1,
    "-webkit-border-bottom-left-radius": 1,

    // dropshadows
    "-moz-box-shadow": 1,
    "-webkit-box-shadow": 1,

    // transformations
    "transform": {"rotate($00deg)": 1, "skew($00deg)": 1},
    "-moz-transform": {"rotate($00deg)": 1, "skew($00deg)": 1},
    "-webkit-transform": {"rotate($00deg)": 1, "skew($00deg)": 1 }
};

var CssCompletions = function() {

};

(function() {

    this.completionsDefined = false;

    this.defineCompletions = function() {
        //fill in missing properties
        if (document) {
            var style = document.createElement('c').style;

            for (var i in style) {
                if (typeof style[i] !== 'string')
                    continue;

                var name = i.replace(/[A-Z]/g, function(x) {
                    return '-' + x.toLowerCase();
                });

                if (!propertyMap.hasOwnProperty(name))
                    propertyMap[name] = 1;
            }
        }

        this.completionsDefined = true;
    };

    this.getCompletions = function(state, session, pos, prefix) {
        if (!this.completionsDefined) {
            this.defineCompletions();
        }

        var token = session.getTokenAt(pos.row, pos.column);

        if (!token)
            return [];
        if (state==='ruleset'){
            //css attribute value
            var line = session.getLine(pos.row).substr(0, pos.column);
            if (/:[^;]+$/.test(line)) {
                /([\w\-]+):[^:]*$/.test(line);

                return this.getPropertyValueCompletions(state, session, pos, prefix);
            } else {
                return this.getPropertyCompletions(state, session, pos, prefix);
            }
        }

        return [];
    };

    this.getPropertyCompletions = function(state, session, pos, prefix) {
        var properties = Object.keys(propertyMap);
        return properties.map(function(property){
            return {
                caption: property,
                snippet: property + ': $0',
                meta: "property",
                score: Number.MAX_VALUE
            };
        });
    };

    this.getPropertyValueCompletions = function(state, session, pos, prefix) {
        var line = session.getLine(pos.row).substr(0, pos.column);
        var property = (/([\w\-]+):[^:]*$/.exec(line) || {})[1];

        if (!property)
            return [];
        var values = [];
        if (property in propertyMap && typeof propertyMap[property] === "object") {
            values = Object.keys(propertyMap[property]);
        }
        return values.map(function(value){
            return {
                caption: value,
                snippet: value,
                meta: "property value",
                score: Number.MAX_VALUE
            };
        });
    };

}).call(CssCompletions.prototype);

exports.CssCompletions = CssCompletions;
});
<commit_msg>Add colon next the cursor when completing a property<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Distributed under the BSD license:
 *
 * Copyright (c) 2010, Ajax.org B.V.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Ajax.org B.V. nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {
"use strict";

var propertyMap = {
    "background": {"#$0": 1},
    "background-color": {"#$0": 1, "transparent": 1, "fixed": 1},
    "background-image": {"url('/$0')": 1},
    "background-repeat": {"repeat": 1, "repeat-x": 1, "repeat-y": 1, "no-repeat": 1, "inherit": 1},
    "background-position": {"bottom":2, "center":2, "left":2, "right":2, "top":2, "inherit":2},
    "background-attachment": {"scroll": 1, "fixed": 1},
    "background-size": {"cover": 1, "contain": 1},
    "background-clip": {"border-box": 1, "padding-box": 1, "content-box": 1},
    "background-origin": {"border-box": 1, "padding-box": 1, "content-box": 1},
    "border": {"solid $0": 1, "dashed $0": 1, "dotted $0": 1, "#$0": 1},
    "border-color": {"#$0": 1},
    "border-style": {"solid":2, "dashed":2, "dotted":2, "double":2, "groove":2, "hidden":2, "inherit":2, "inset":2, "none":2, "outset":2, "ridged":2},
    "border-collapse": {"collapse": 1, "separate": 1},
    "bottom": {"px": 1, "em": 1, "%": 1},
    "clear": {"left": 1, "right": 1, "both": 1, "none": 1},
    "color": {"#$0": 1, "rgb(#$00,0,0)": 1},
    "cursor": {"default": 1, "pointer": 1, "move": 1, "text": 1, "wait": 1, "help": 1, "progress": 1, "n-resize": 1, "ne-resize": 1, "e-resize": 1, "se-resize": 1, "s-resize": 1, "sw-resize": 1, "w-resize": 1, "nw-resize": 1},
    "display": {"none": 1, "block": 1, "inline": 1, "inline-block": 1, "table-cell": 1},
    "empty-cells": {"show": 1, "hide": 1},
    "float": {"left": 1, "right": 1, "none": 1},
    "font-family": {"Arial":2,"Comic Sans MS":2,"Consolas":2,"Courier New":2,"Courier":2,"Georgia":2,"Monospace":2,"Sans-Serif":2, "Segoe UI":2,"Tahoma":2,"Times New Roman":2,"Trebuchet MS":2,"Verdana": 1},
    "font-size": {"px": 1, "em": 1, "%": 1},
    "font-weight": {"bold": 1, "normal": 1},
    "font-style": {"italic": 1, "normal": 1},
    "font-variant": {"normal": 1, "small-caps": 1},
    "height": {"px": 1, "em": 1, "%": 1},
    "left": {"px": 1, "em": 1, "%": 1},
    "letter-spacing": {"normal": 1},
    "line-height": {"normal": 1},
    "list-style-type": {"none": 1, "disc": 1, "circle": 1, "square": 1, "decimal": 1, "decimal-leading-zero": 1, "lower-roman": 1, "upper-roman": 1, "lower-greek": 1, "lower-latin": 1, "upper-latin": 1, "georgian": 1, "lower-alpha": 1, "upper-alpha": 1},
    "margin": {"px": 1, "em": 1, "%": 1},
    "margin-right": {"px": 1, "em": 1, "%": 1},
    "margin-left": {"px": 1, "em": 1, "%": 1},
    "margin-top": {"px": 1, "em": 1, "%": 1},
    "margin-bottom": {"px": 1, "em": 1, "%": 1},
    "max-height": {"px": 1, "em": 1, "%": 1},
    "max-width": {"px": 1, "em": 1, "%": 1},
    "min-height": {"px": 1, "em": 1, "%": 1},
    "min-width": {"px": 1, "em": 1, "%": 1},
    "overflow": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "overflow-x": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "overflow-y": {"hidden": 1, "visible": 1, "auto": 1, "scroll": 1},
    "padding": {"px": 1, "em": 1, "%": 1},
    "padding-top": {"px": 1, "em": 1, "%": 1},
    "padding-right": {"px": 1, "em": 1, "%": 1},
    "padding-bottom": {"px": 1, "em": 1, "%": 1},
    "padding-left": {"px": 1, "em": 1, "%": 1},
    "page-break-after": {"auto": 1, "always": 1, "avoid": 1, "left": 1, "right": 1},
    "page-break-before": {"auto": 1, "always": 1, "avoid": 1, "left": 1, "right": 1},
    "position": {"absolute": 1, "relative": 1, "fixed": 1, "static": 1},
    "right": {"px": 1, "em": 1, "%": 1},
    "table-layout": {"fixed": 1, "auto": 1},
    "text-decoration": {"none": 1, "underline": 1, "line-through": 1, "blink": 1},
    "text-align": {"left": 1, "right": 1, "center": 1, "justify": 1},
    "text-transform": {"capitalize": 1, "uppercase": 1, "lowercase": 1, "none": 1},
    "top": {"px": 1, "em": 1, "%": 1},
    "vertical-align": {"top": 1, "bottom": 1},
    "visibility": {"hidden": 1, "visible": 1},
    "white-space": {"nowrap": 1, "normal": 1, "pre": 1, "pre-line": 1, "pre-wrap": 1},
    "width": {"px": 1, "em": 1, "%": 1},
    "word-spacing": {"normal": 1},

    // opacity
    "filter": {"alpha(opacity=$0100)": 1},

    "text-shadow": {"$02px 2px 2px #777": 1},
    "text-overflow": {"ellipsis-word": 1, "clip": 1, "ellipsis": 1},

    // border radius
    "-moz-border-radius": 1,
    "-moz-border-radius-topright": 1,
    "-moz-border-radius-bottomright": 1,
    "-moz-border-radius-topleft": 1,
    "-moz-border-radius-bottomleft": 1,
    "-webkit-border-radius": 1,
    "-webkit-border-top-right-radius": 1,
    "-webkit-border-top-left-radius": 1,
    "-webkit-border-bottom-right-radius": 1,
    "-webkit-border-bottom-left-radius": 1,

    // dropshadows
    "-moz-box-shadow": 1,
    "-webkit-box-shadow": 1,

    // transformations
    "transform": {"rotate($00deg)": 1, "skew($00deg)": 1},
    "-moz-transform": {"rotate($00deg)": 1, "skew($00deg)": 1},
    "-webkit-transform": {"rotate($00deg)": 1, "skew($00deg)": 1 }
};

var CssCompletions = function() {

};

(function() {

    this.completionsDefined = false;

    this.defineCompletions = function() {
        //fill in missing properties
        if (document) {
            var style = document.createElement('c').style;

            for (var i in style) {
                if (typeof style[i] !== 'string')
                    continue;

                var name = i.replace(/[A-Z]/g, function(x) {
                    return '-' + x.toLowerCase();
                });

                if (!propertyMap.hasOwnProperty(name))
                    propertyMap[name] = 1;
            }
        }

        this.completionsDefined = true;
    };

    this.getCompletions = function(state, session, pos, prefix) {
        if (!this.completionsDefined) {
            this.defineCompletions();
        }

        var token = session.getTokenAt(pos.row, pos.column);

        if (!token)
            return [];
        if (state==='ruleset'){
            //css attribute value
            var line = session.getLine(pos.row).substr(0, pos.column);
            if (/:[^;]+$/.test(line)) {
                /([\w\-]+):[^:]*$/.test(line);

                return this.getPropertyValueCompletions(state, session, pos, prefix);
            } else {
                return this.getPropertyCompletions(state, session, pos, prefix);
            }
        }

        return [];
    };

    this.getPropertyCompletions = function(state, session, pos, prefix) {
        var properties = Object.keys(propertyMap);
        return properties.map(function(property){
            return {
                caption: property,
                snippet: property + ': $0;',
                meta: "property",
                score: Number.MAX_VALUE
            };
        });
    };

    this.getPropertyValueCompletions = function(state, session, pos, prefix) {
        var line = session.getLine(pos.row).substr(0, pos.column);
        var property = (/([\w\-]+):[^:]*$/.exec(line) || {})[1];

        if (!property)
            return [];
        var values = [];
        if (property in propertyMap && typeof propertyMap[property] === "object") {
            values = Object.keys(propertyMap[property]);
        }
        return values.map(function(value){
            return {
                caption: value,
                snippet: value,
                meta: "property value",
                score: Number.MAX_VALUE
            };
        });
    };

}).call(CssCompletions.prototype);

exports.CssCompletions = CssCompletions;
});
<|endoftext|>