<commit_before>﻿module DarkReader {

    export interface FilterConfig {
        mode: FilterMode;
        brightness: number;
        contrast: number;
        grayscale: number;
        sepia: number;
        useFont: boolean;
        fontFamily: string;
        textStroke: number;
        siteList: string[];
        invertListed: boolean;
        
        // OBSOLETE
        //usefont: boolean;
        //fontfamily: string;
        //textstroke: number;
        //ignorelist: string[];
    }

    export interface ObsoleteFilterConfig {
        usefont: boolean;
        fontfamily: string;
        textstroke: number;
        ignorelist: string[];
    }

    export enum FilterMode {
        light = 0,
        dark = 1
    }

    export var DEFAULT_FILTER_CONFIG: DarkReader.FilterConfig = {
        mode: DarkReader.FilterMode.dark,
        brightness: 110,
        contrast: 90,
        grayscale: 20,
        sepia: 10,
        useFont: false,
        fontFamily: 'Segoe UI',
        textStroke: 0,
        invertListed: false,
        siteList: []
    };

    /**
     * Configurable CSS-generator based on CSS-filters.
     * It creates rule to invert a whole page and creates another rule to revert specific blocks back.
     */
    export class FilterCssGenerator {

        /**
         * Creates configurable CSS-generator based on CSS-filters.
         */
        constructor() {
            // Detect Chromium issue 501582
            var m = navigator.userAgent.toLowerCase().match(/chrom[e|ium]\/([^ ]+)/);
            if (m && m[1]) {
                var chromeVersion = m[1];
                if (chromeVersion >= '45.0.2431.0') {
                    this.issue501582 = true;
                }
            }
        }

        issue501582: boolean;

        /**
         * Generates CSS code.
         * @param config Generator configuration.
         * @param url Web-site address.
         */
        createCssCode(config: FilterConfig, url: string): string {
            var isUrlInDarkList = isUrlInList(url, DARK_SITES);
            var isUrlInUserList = isUrlInList(url, config.siteList);

            if ((isUrlInUserList && config.invertListed)
                || (!isUrlInDarkList
                    && !config.invertListed
                    && !isUrlInUserList)
            ) {
                console.log('Creating CSS for url: ' + url);

                // Search for custom fix
                var fix = getFixesFor(url);
                
                //
                // Combine CSS

                var parts: string[] = [];

                parts.push('@media screen {');

                // Add leading rule.
                parts.push(this.createLeadingRule(config));

                if (config.mode === FilterMode.dark)
                    // Add contrary rule
                    if (fix.selectors) {
                        parts.push(this.createContraryRule(config, fix.selectors));
                    }

                if (config.useFont || config.textStroke > 0) {
                    // Add text rule
                    parts.push(`* ${this.createTextDeclaration(config)}`);
                }

                // Fix bad font hinting after inversion                    
                parts.push('html { text-shadow: 0 0 0 !important; }');

                // Fix <html> height
                parts.push('html { min-height: 100% !important; }');

                // Full screen fix
                parts.push('*:-webkit-full-screen, *:-webkit-full-screen * { -webkit-filter: none !important; }');

                // --- WARNING! HACK! ---
                if (this.issue501582) {
                    // NOTE: Chrome 45 temp <html> background fix
                    // https://code.google.com/p/chromium/issues/detail?id=501582
                    
                    //
                    // Interpolate background color (fastest, no script required).
                    // http://www.w3.org/TR/filter-effects/#brightnessEquivalent
                    
                    // Brightness
                    var value = config.mode === FilterMode.dark ? 0 : 1;
                    value = value * (config.brightness) / 100;
                    
                    // Contrast<commit_msg>Fixed #23 Added some text stroke for emphasis tags.<commit_after>﻿module DarkReader {

    export interface FilterConfig {
        mode: FilterMode;
        brightness: number;
        contrast: number;
        grayscale: number;
        sepia: number;
        useFont: boolean;
        fontFamily: string;
        textStroke: number;
        siteList: string[];
        invertListed: boolean;
        
        // OBSOLETE
        //usefont: boolean;
        //fontfamily: string;
        //textstroke: number;
        //ignorelist: string[];
    }

    export interface ObsoleteFilterConfig {
        usefont: boolean;
        fontfamily: string;
        textstroke: number;
        ignorelist: string[];
    }

    export enum FilterMode {
        light = 0,
        dark = 1
    }

    export var DEFAULT_FILTER_CONFIG: DarkReader.FilterConfig = {
        mode: DarkReader.FilterMode.dark,
        brightness: 110,
        contrast: 90,
        grayscale: 20,
        sepia: 10,
        useFont: false,
        fontFamily: 'Segoe UI',
        textStroke: 0,
        invertListed: false,
        siteList: []
    };

    /**
     * Configurable CSS-generator based on CSS-filters.
     * It creates rule to invert a whole page and creates another rule to revert specific blocks back.
     */
    export class FilterCssGenerator {

        /**
         * Creates configurable CSS-generator based on CSS-filters.
         */
        constructor() {
            // Detect Chromium issue 501582
            var m = navigator.userAgent.toLowerCase().match(/chrom[e|ium]\/([^ ]+)/);
            if (m && m[1]) {
                var chromeVersion = m[1];
                if (chromeVersion >= '45.0.2431.0') {
                    this.issue501582 = true;
                }
            }
        }

        issue501582: boolean;

        /**
         * Generates CSS code.
         * @param config Generator configuration.
         * @param url Web-site address.
         */
        createCssCode(config: FilterConfig, url: string): string {
            var isUrlInDarkList = isUrlInList(url, DARK_SITES);
            var isUrlInUserList = isUrlInList(url, config.siteList);

            if ((isUrlInUserList && config.invertListed)
                || (!isUrlInDarkList
                    && !config.invertListed
                    && !isUrlInUserList)
            ) {
                console.log('Creating CSS for url: ' + url);

                // Search for custom fix
                var fix = getFixesFor(url);
                
                //
                // Combine CSS

                var parts: string[] = [];

                parts.push('@media screen {');

                // Add leading rule.
                parts.push(this.createLeadingRule(config));

                if (config.mode === FilterMode.dark)
                    // Add contrary rule
                    if (fix.selectors) {
                        parts.push(this.createContraryRule(config, fix.selectors));
                    }

                if (config.useFont || config.textStroke > 0) {
                    // Add text rule
                    parts.push(`* ${this.createTextDeclaration(config)}`);
                }

                // Fix bad font hinting after inversion
                parts.push('html { text-shadow: 0 0 0 !important; }');
                parts.push('em, strong, b { -webkit-text-stroke: 0.5px; }');

                // Fix <html> height
                parts.push('html { min-height: 100% !important; }');

                // Full screen fix
                parts.push('*:-webkit-full-screen, *:-webkit-full-screen * { -webkit-filter: none !important; }');

                // --- WARNING! HACK! ---
                if (this.issue501582) {
                    // NOTE: Chrome 45 temp <html> background fix
                    // https://code.google.com/p/chromium/issues/detail?id=501582
                    
                    //
                    // Interpolate background color (fastest, no script required).
                    // http://www.w3.org/TR/filter-effects/#brightnessEquivalent
                    
                    // Brightness
                    var value = config.mode === FilterMode.dark ? 0 : 1;
                    value = value * (config.brightness) / 100;
                    
                    // Contrast
{'fraction_non_alphanumeric': 0.10580165097081734, 'fraction_numerical': 0.016044645971398673, 'mean_word_length': 1.2926439232409381, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6186985', 'n_tokens_mistral': 2411, 'n_tokens_neox': 2164, 'n_words': 530}