<commit_before>(function() {
  const fileUtils = require("./file-utils");
  const puppeteer = require("puppeteer");
  const jsdom = require("jsdom");

  // Order matters (tree/master/src/bookmarklet)
  const bookmarkletList = [
    "analyzer",
    "crafting",
    "cre",
    "crown",
    "loader",
    "map",
    "menu",
    "powers",
    "setup_fields",
    "setup_items"
  ];

  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * Parses datetime data from master/src/bookmarklet HTML
   * @param {string} htmlUrl
   */
  async function fetchTimestamps(htmlUrl) {
    const browser = await puppeteer.launch({
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
      executablePath: "google-chrome-stable"
      // executablePath:
      //   "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
    });

    // 2 throwaway pages to try and avoid "Failed to load latest commit information"
    // const prePage1 = await browser.newPage();
    // await prePage1.goto(htmlUrl);
    // const preBody1 = await prePage1.content();
    // await sleep(200);
    // await prePage1.close();
    // await sleep(300);
    // const prePage2 = await browser.newPage();
    // await prePage2.goto(htmlUrl);
    // const preBody2 = await prePage2.content();
    // await sleep(200);
    // await prePage2.close();
    // await sleep(300);
    const page = await browser.newPage();
    await page.goto(htmlUrl);
    const body = await page.content();
    // await page.close();
    // await browser.close();

    const { JSDOM } = jsdom;
    const dom = new JSDOM(`${body}`);
    const document = dom.window.document;

    const result = [];
    document.querySelectorAll("time-ago").forEach(el => {
      result.push(el.title);
    });

    return result;
  }

  (async function main() {
    const res = await fetchTimestamps(
      "https://github.com/tsitu/MH-Tools/tree/master/src/bookmarklet"
    ).catch(error => console.log(error));

    console.log(res);

    const format = res.map(el => {
      const spl = el.split(", ");
      return `${spl[0]}, ${spl[1]}`;
    });

    const bookmarkletJson = {};
    for (let i = 0; i < bookmarkletList.length; i++) {
      bookmarkletJson[bookmarkletList[i]] = format[i];
    }

    console.log(bookmarkletJson);

    fileUtils.saveJsonFile(
      "data/json/bookmarklet-timestamps.json",
      bookmarkletJson
    );
  })();
})();
<commit_msg>Added debug log statements to process-timestamp<commit_after>(function() {
  const fileUtils = require("./file-utils");
  const puppeteer = require("puppeteer");
  const jsdom = require("jsdom");

  // Order matters (tree/master/src/bookmarklet)
  const bookmarkletList = [
    "analyzer",
    "crafting",
    "cre",
    "crown",
    "loader",
    "map",
    "menu",
    "powers",
    "setup_fields",
    "setup_items"
  ];

  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * Parses datetime data from master/src/bookmarklet HTML
   * @param {string} htmlUrl
   */
  async function fetchTimestamps(htmlUrl) {
    console.log("Initializing Puppeteer browser...");

    const browser = await puppeteer.launch({
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
      executablePath: "google-chrome-stable"
      // executablePath:
      //   "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"
    });

    console.log("Initialization complete. Loading pages...");

    // 2 throwaway pages to try and avoid "Failed to load latest commit information"
    // const prePage1 = await browser.newPage();
    // await prePage1.goto(htmlUrl);
    // const preBody1 = await prePage1.content();
    // await sleep(200);
    // await prePage1.close();
    // await sleep(300);
    // const prePage2 = await browser.newPage();
    // await prePage2.goto(htmlUrl);
    // const preBody2 = await prePage2.content();
    // await sleep(200);
    // await prePage2.close();
    // await sleep(300);
    const page = await browser.newPage();
    console.log("New page object instantiated...");
    await page.goto(htmlUrl);
    console.log("Navigated to GH URL...");
    const body = await page.content();
    console.log("Page body acquired...");
    // await page.close();
    // await browser.close();

    const { JSDOM } = jsdom;
    const dom = new JSDOM(`${body}`);
    const document = dom.window.document;

    const result = [];
    document.querySelectorAll("time-ago").forEach(el => {
      result.push(el.title);
    });

    return result;
  }

  (async function main() {
    console.log("Begin fetchTimestamps routine...");

    const res = await fetchTimestamps(
      "https://github.com/tsitu/MH-Tools/tree/master/src/bookmarklet"
    ).catch(error => console.log(error));

    console.log(res);

    const format = res.map(el => {
      const spl = el.split(", ");
      return `${spl[0]}, ${spl[1]}`;
    });

    const bookmarkletJson = {};
    for (let i = 0; i < bookmarkletList.length; i++) {
      bookmarkletJson[bookmarkletList[i]] = format[i];
    }

    console.log(bookmarkletJson);

    fileUtils.saveJsonFile(
      "data/json/bookmarklet-timestamps.json",
      bookmarkletJson
    );
  })();
})();
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * Logology V{{{VERSION}}}
 * Author: {{{AUTHOR.NAME}}} <{{{AUTHOR.EMAIL}}}> <{{{AUTHOR.SITE}}}>
 *
 * This is a very simple demonstration of using gulp + ES6; it obviously
 * doesn't do anything resembling the goal of the app yet.
 *
 *****************************************************************************/

/*globals MobileAccessibility, setImmediate*/

import "babel/polyfill";
import h from "yasmf-h";

//h.useDomMerging = true;

import Emitter from "yasmf-emitter";
import GCS from "../lib/grandCentralStation";
import SoftKeyboard from "../lib/SoftKeyboard";
import L from "./localization/localization";

import Theme from "../lib/Theme";
import ThemeManager from "../lib/ThemeManager";

import NavigationViewController from "../lib/NavigationViewController.js";

import Settings from "./models/Settings";
import Dictionaries from "./models/Dictionaries";
import StarterDictionary from "./models/StarterDictionary";

/*
function simpleAlert() {
    let outerDiv = document.createElement("div"),
        innerDiv = document.createElement("div"),
        titleEl  = document.createElement("h1"),
        messageEl =  document.createElement("p"),
        buttonEl = document.createElement("button"),
        mainWindow = document.getElementById("mainWindow");
    outerDiv.setAttribute("is", "y-alert-container");
    innerDiv.setAttribute("is", "y-alert-dialog");
    titleEl.textContent = "Important!";
    messageEl.textContent = "This is an important message. Close this by tapping OK.";
    buttonEl.textContent = "OK";

    // accessibility
    innerDiv.setAttribute("role", "alertdialog");
    messageEl.setAttribute("role", "alert");

    // create the dom structure
    outerDiv.appendChild(innerDiv);
    innerDiv.appendChild(titleEl);
    innerDiv.appendChild(messageEl);
    innerDiv.appendChild(buttonEl);

    document.body.appendChild(outerDiv);
    setTimeout(function () {
      outerDiv.classList.add("visible");
      mainWindow.setAttribute("aria-hidden", true);
      buttonEl.focus();
    }, 0);

    buttonEl.addEventListener("click", function() {
        outerDiv.classList.remove("visible");
        setTimeout(function() {
          mainWindow.removeAttribute("aria-hidden");
          document.body.removeChild(outerDiv);
        }, 400);
    }, false);
}
*/

import SearchViewController from "./controllers/SearchViewController";

class App extends Emitter {
    constructor() {
        super();
        //document.addEventListener("deviceready", this.start.bind(this), false);
        document.addEventListener("DOMContentLoaded", this.start.bind(this), false);
        this.GCS = GCS;
        GCS.on("APP:startupFailure", this.onStartupFailure, this);
    }

    onStartupFailure(sender, notice, err) {
        console.log(`Startup failure ${err}`);
    }

    async start() {

//        try {

            // zoom our text for accessibility
            if (typeof MobileAccessibility !== "undefined") {
                MobileAccessibility.usePreferredTextZoom(true);
            }

            // load localization information
            let locale = await L.loadLocale();
            this.locale = locale;
            this.L = L;
            L.loadTranslations(require("./localization/root/messages"));

            // load theme
            this.theme = new Theme();
            this.themeManager = new ThemeManager();
            this.themeManager.currentTheme = this.theme;

            // load settings
            this.settings = new Settings();

            // create dictionaries list
            this.dictionaries = new Dictionaries();
            this.dictionaries.addDictionary(StarterDictionary);

            this.searchViewController = new SearchViewController({model: new StarterDictionary()});
            this.searchViewController2 = new SearchViewController({model: new StarterDictionary()});
            //this.searchViewController.renderElement = document.getElementById("mainWindow");

            this.navigationViewController = new NavigationViewController({subviews: [this.searchViewController],
                                                                          themeManager: this.themeManager,
                                                                          renderElement: document.getElementById("mainWindow")});

            // tell everyone that the app has started
            GCS.emit("APP:started");
            this.emit("started");
 /*       } catch (err) {
            GCS.emit("APP:startupFailure", err);
            this.emit("startupFailure", err);
        }*/

        //document.querySelector("[is='y-menu-glyph']").addEventListener("click", simpleAlert, false);
        this.softKeyboard = new SoftKeyboard({selectors: [".ui-scroll-container", "[is='y-scroll-container']", "y-scroll-container"]});
    }
}

let app = new App();
export default app;
<commit_msg>play around with split view<commit_after>/*****************************************************************************
 *
 * Logology V{{{VERSION}}}
 * Author: {{{AUTHOR.NAME}}} <{{{AUTHOR.EMAIL}}}> <{{{AUTHOR.SITE}}}>
 *
 * This is a very simple demonstration of using gulp + ES6; it obviously
 * doesn't do anything resembling the goal of the app yet.
 *
 *****************************************************************************/

/*globals MobileAccessibility, setImmediate*/

import "babel/polyfill";
import h from "yasmf-h";

import once from "once";

import Emitter from "yasmf-emitter";
import GCS from "../lib/grandCentralStation";
import SoftKeyboard from "../lib/SoftKeyboard";
import L from "./localization/localization";

import Theme from "../lib/Theme";
import ThemeManager from "../lib/ThemeManager";

import NavigationViewController from "../lib/NavigationViewController";
import SplitViewController from "../lib/SplitViewController";

import Settings from "./models/Settings";
import Dictionaries from "./models/Dictionaries";
import StarterDictionary from "./models/StarterDictionary";

/*
function simpleAlert() {
    let outerDiv = document.createElement("div"),
        innerDiv = document.createElement("div"),
        titleEl  = document.createElement("h1"),
        messageEl =  document.createElement("p"),
        buttonEl = document.createElement("button"),
        mainWindow = document.getElementById("mainWindow");
    outerDiv.setAttribute("is", "y-alert-container");
    innerDiv.setAttribute("is", "y-alert-dialog");
    titleEl.textContent = "Important!";
    messageEl.textContent = "This is an important message. Close this by tapping OK.";
    buttonEl.textContent = "OK";

    // accessibility
    innerDiv.setAttribute("role", "alertdialog");
    messageEl.setAttribute("role", "alert");

    // create the dom structure
    outerDiv.appendChild(innerDiv);
    innerDiv.appendChild(titleEl);
    innerDiv.appendChild(messageEl);
    innerDiv.appendChild(buttonEl);

    document.body.appendChild(outerDiv);
    setTimeout(function () {
      outerDiv.classList.add("visible");
      mainWindow.setAttribute("aria-hidden", true);
      buttonEl.focus();
    }, 0);

    buttonEl.addEventListener("click", function() {
        outerDiv.classList.remove("visible");
        setTimeout(function() {
          mainWindow.removeAttribute("aria-hidden");
          document.body.removeChild(outerDiv);
        }, 400);
    }, false);
}
*/

import SearchViewController from "./controllers/SearchViewController";

class App extends Emitter {
    constructor() {
        super();
        let startAppOnce = once(this.start.bind(this));
        document.addEventListener("deviceready", this.startAppOnce, false);
        document.addEventListener("DOMContentLoaded", () => {
            setTimeout(startAppOnce, 1000);
        }, false);
        GCS.on("APP:startupFailure", this.onStartupFailure, this);

        // DEBUG: debugging only
        this.GCS = GCS;
    }

    onStartupFailure(sender, notice, err) {
        console.log(`Startup failure ${err}`);
    }

    async start() {

        try {
            // zoom our text for accessibility
            if (typeof MobileAccessibility !== "undefined") {
                MobileAccessibility.usePreferredTextZoom(true);
            }

            // load localization information
            this.locale = await L.loadLocale();

            this.L = L; // DEBUG: testing only

            L.loadTranslations(require("./localization/root/messages"));

            // load theme
            this.theme = new Theme();
            this.themeManager = new ThemeManager();
            this.themeManager.currentTheme = this.theme;

            // load settings
            this.settings = new Settings();

            // create dictionaries list
            this.dictionaries = new Dictionaries();
            this.dictionaries.addDictionary(StarterDictionary);

            this.searchViewController = new SearchViewController({model: new StarterDictionary()});
            this.searchViewController2 = new SearchViewController({model: new StarterDictionary()});

            /*
            this.navigationViewController = new NavigationViewController({subviews: [this.searchViewController],
                                                                          themeManager: this.themeManager,
                                                                          renderElement: document.getElementById("mainWindow")});
            this.navigationViewController.visible = true;
            */
            this.splitViewController = new SplitViewController({subviews: [this.searchViewController,
                                                                           this.searchViewController2],
                                                                themeManager: this.themeManager,
                                                                renderElement: document.getElementById("mainWindow")});
            this.splitViewController.visible = true;
            // tell everyone that the app has started
            GCS.emit("APP:started");
            this.emit("started");
        } catch (err) {
            GCS.emit("APP:startupFailure", err);
            this.emit("startupFailure", err);
        }

        //document.querySelector("[is='y-menu-glyph']").addEventListener("click", simpleAlert, false);
        this.softKeyboard = new SoftKeyboard({selectors: [".ui-scroll-container", "[is='y-scroll-container']", "y-scroll-container"]});
    }
}

let app = new App();
export default app;
<|endoftext|>


<commit_before>BreakoutGame.Brick = function (index) {
    if (index === undefined) {
        console.error("index not defined");
    } else {
        if (index > 23)
            index = 23;
    }

    GameFramework.Sprite.call(this, GameFramework.SpriteFactory.loadedSpriteSheets["images/bricks.png"]);

    this.glow = GameFramework.SpriteFactory.spriteFromSpriteSheet("images/bricksGlow.png");
    this._spriteIndex = index;
};

BreakoutGame.Brick.prototype = new GameFramework.Sprite();

BreakoutGame.Brick.prototype.glowIndex = function (brickIndex) {
    if (brickIndex < 4) {
        return 0;
    } else if (brickIndex < 8) {
        return 1;
    } else if (brickIndex < 12) {
        return 3;
    } else if (brickIndex < 19) {
        return 4;
    }
    return 5;
};

BreakoutGame.Brick.prototype.init = function () {
    GameFramework.Sprite.prototype.init.apply(this);
    this.glow.init();
};

BreakoutGame.Brick.prototype.spriteIndex = function(index) {
    GameFramework.Sprite.prototype.spriteIndex.apply(this, [index]);
    this.glow.spriteIndex(this.glowIndex(index));
};

BreakoutGame.Brick.prototype.update = function (time) {
    GameFramework.Sprite.prototype.update.apply(this, [time]);

    this._timeInCurrentIndex += time.deltaTime;

    // this.spriteIndex((this.spriteIndex() + 1) % this._maxIndex);

    this.glow.transform = this.transform;
    this.glow.update(time);
};

BreakoutGame.Brick.prototype.render = function (time, context2D, debugDraw) {
    this.glow.render(time, context2D, false);
    GameFramework.Sprite.prototype.render.apply(this, [time, context2D, debugDraw]);
};

BreakoutGame.Brick.prototype.dispose = function () {
    GameFramework.Sprite.prototype.dispose();
    this.glow.dispose();
};
<commit_msg>Fixing glowIndex method to return correct index.<commit_after>BreakoutGame.Brick = function (index) {
    if (index === undefined) {
        console.error("index not defined");
    } else {
        if (index > 23)
            index = 23;
    }

    GameFramework.Sprite.call(this, GameFramework.SpriteFactory.loadedSpriteSheets["images/bricks.png"]);

    this.glow = GameFramework.SpriteFactory.spriteFromSpriteSheet("images/bricksGlow.png");
    this._spriteIndex = index;
};

BreakoutGame.Brick.prototype = new GameFramework.Sprite();

BreakoutGame.Brick.prototype.glowIndex = function (brickIndex) {
    if (brickIndex < 4) {
        return 0;
    } else if (brickIndex < 8) {
        return 1;
    } else if (brickIndex < 12) {
        return 2;
    } else if (brickIndex < 19) {
        return 3;
    }
    return 4;
};

BreakoutGame.Brick.prototype.init = function () {
    GameFramework.Sprite.prototype.init.apply(this);
    this.glow.init();
};

BreakoutGame.Brick.prototype.spriteIndex = function(index) {
    GameFramework.Sprite.prototype.spriteIndex.apply(this, [index]);
    this.glow.spriteIndex(this.glowIndex(index));
};

BreakoutGame.Brick.prototype.update = function (time) {
    GameFramework.Sprite.prototype.update.apply(this, [time]);

    this._timeInCurrentIndex += time.deltaTime;

    // this.spriteIndex((this.spriteIndex() + 1) % this._maxIndex);

    this.glow.transform = this.transform;
    this.glow.update(time);
};

BreakoutGame.Brick.prototype.render = function (time, context2D, debugDraw) {
    this.glow.opacity = this.opacity;
    this.glow.render(time, context2D, false);
    GameFramework.Sprite.prototype.render.apply(this, [time, context2D, debugDraw]);
};

BreakoutGame.Brick.prototype.dispose = function () {
    GameFramework.Sprite.prototype.dispose();
    this.glow.dispose();
};
<|endoftext|>


<commit_before>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 * See http://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript for formating conventions
 */
( function( mw, $ ){ "use strict";

window['mwePlayerId'];
mw.EmbedPlayerYouTube = {

	//test comment for testing pull request

	// Instance name:
	instanceOf : 'youtube',

	bindPostfix: '.YouTube',
	//current playhead time
	time : 0,
	//current entry duration
	duration : 0,
	// A flag to store if the player has already been embed or not
	playerEmbedFlag: false,
	//Flag holdinng end state
	hasEnded: false,

	//the youtube entry id
	youtubeEntryId : "",

	//the youtube preFix
	//TODO grab from a configuration
	youtubePreFix : "//www.youtube.com/apiplayer?video_id=",
	youtubeProtocol : "http:",
	// List of supported features:
	supports : {
		'playHead' :  (mw.getConfig('previewMode') == null) ? true : false ,
		'pause' : true,
		'stop' : true,
		'timeDisplay' : true,
		'volumeControl' : true,
		'overlays' : true,
		'fullscreen' : (mw.getConfig('previewMode') == null) ? true : false
	},

	init: function(){
		var _this = this;
	},
	onPlayerStateChange : function (event){
		//delegate to window function
		window['onPlayerStateChange'](event);
	},

	registerGlobalCallbacks: function(){
		var _this = this;
		window['onPlayerStateChange'] = function( event ){
			var _this = $('#' + window['mwePlayerId'])[0];
			// clean up
			if( event.data || event.data == 0 || event.data ){
				event = event.data;
			}
			var stateName;
			// move to other method
			switch( event ){
				case -1:
					stateName = "unstarted";

				  break;
				case 0:
				case "0":
					stateName = "ended";
					this.hasEnded = true;
				  break;
				case 1:
					// hide the player container so that youtube click through work
					$('.mwEmbedPlayer').hide();
					//hide the poster
					$(".playerPoster").hide();
					$('.blackBoxHide').hide();
					_this.play();
					stateName = "playing";
					//$(this).hide();
					// update duraiton
					_this.setDuration();
					// trigger the seeked event only if this is seek and not in play
					if(_this.seeking){
						_this.seeking = false;
						$( _this ).trigger( 'seeked' );
						// update the playhead status
						_this.updatePlayheadStatus();
					}
				  break;
				case 2:
					stateName = "paused";
					_this.parent_pause();
				  break;
				case 3:
					stateName = "buffering";
				  break;
				case 4:
					stateName = "unbuffering";
					break;
				case 5:
					stateName = "video cued";
				  break;
			}

		};
		window['hidePlayer'] = function( event ){
			$('.playerPoster').before('

');
		}
		window['onError'] = function( event ){
			mw.log("Error! YouTubePlayer" ,2);
			$('#loadingSpinner_kaltura_player').append('
Error!');
			var errorMessage;
			if (event.data)
				event = event.data;
			switch( event ){
			case 2:
				errorMessage = "The request contains an invalid parameter value.";
				break;
			case 100:
				errorMessage = "The video requested was not found";
				break;
			case 101:
			case 150:
				errorMessage = "The owner of the requested video does not allow it to be played in embedded players";
				break;
			}
			$('#loadingSpinner_kaltura_player').append('
'+errorMessage);
			$(".playerPoster").hide();
			mw.log(errorMessage ,2);
		};
		//YOUTUBE IFRAME PLAYER READY (Not the Iframe - the player itself)
		window['onIframePlayerReady'] = function( event ){
			//autoplay
			$('#pid_kaltura_player').after('

');
			window['iframePlayer'] = event.target;
            //autoplay
            if(mw.getConfig('autoPlay')){
                  _this.play();
            }else{
                  window['hidePlayer']();
            }

		};
		// YOUTUBE FLASH PLAYER READY
		window['onYouTubePlayerReady'] = function( playerIdStr ){
			$('.ui-icon-image').hide()
			$('#pid_kaltura_player').after('

');
			var flashPlayer = $( '#' + playerIdStr )[0];
			flashPlayer.addEventListener("onStateChange", "onPlayerStateChange");
			flashPlayer.addEventListener("onError", "onError");
            //autoplay
            if(mw.getConfig('autoPlay')){
                  _this.play();
            }else{
                  window['hidePlayer']();
            }

		};
		// YOUTUBE IFRAME READY
		window['onYouTubeIframeAPIReady'] = function( playerIdStr ){
			$('.ui-icon-image').hide()
			//move to the other scope
            var embedPlayer = $('#' + window["pid"].replace( 'pid_', '' ) )[0];
            var playerVars;
            //basic configuration
            playerVars = {
                         controls: 0,
                         iv_load_policy:3,
                         rel: 0,
                         fs: 0,
                         wmode: 'opaque',
                         showinfo:0
            };

            if(window['KeyValueParams'])
            {
                  var kevarsArray = window['KeyValueParams'].split("&");
                  for(var i=0;i<kevarsArray.length;i++){
                         var kv = kevarsArray[i].split("=");
                         playerVars[kv[0]] = kv[1];
                  }

            }
            embedPlayer.playerElement = new YT.Player(pid,
                  {
                         height: '100%',
                         width: '100%',
                         videoId: window["youtubeEntryId"],
                         playerVars: playerVars,
                         events: {
                                'onReady': onIframePlayerReady,
                                'onError': onError,
                                'onStateChange': onPlayerStateChange
                         }
			});
		};
	},

	/*
	 * Write the Embed html to the target
	 */
	embedPlayerHTML : function(){
		this.registerGlobalCallbacks();
		if( this.playerEmbedFlag ){
			return ;
		}
		window['mwePlayerId'] = this.id;
		//handle fetching the youtubeId
		var metadata = this.evaluate('{mediaProxy.entryMetadata}');
		var entry = this.evaluate('{mediaProxy.entry}');
		//look for referenceId and then for custom data field YoutubeId
		if(entry.referenceId)
			this.youtubeEntryId = entry.referenceId;
		if(metadata.YoutubeId)
			this.youtubeEntryId = metadata.YoutubeId;

		if(this.youtubeEntryId.indexOf('http') > -1 || this.youtubeEntryId.indexOf('youtube') > -1  ){
			//found a full path - parse the entryId from it:
			var arr = this.youtubeEntryId.split("v=");
			var newEntryId = arr[1];
			if (newEntryId.indexOf("#") > -1)
				newEntryId = newEntryId.split("#")[0];
			if (newEntryId.indexOf("&") > -1)
				newEntryId = newEntryId.split("&")[0];
			this.youtubeEntryId = newEntryId;
		}

		this.youtubeEntryId = "fffffffffffffffffffffff";

		if(metadata.KeyValueParams){
			window['KeyValueParams'] = metadata.KeyValueParams;
		}
		window['pid'] = this.pid;

		if(mw.getConfig("forceYoutubeEntry"))
		{
			this.youtubeEntryId=mw.getConfig("forceYoutubeEntry");
		}
		window["youtubeEntryId"] = this.youtubeEntryId;

		this.playerEmbedFlag = true;
		this.youtubeProtocol = location.protocol;
		this.youtubePreFix = this.youtubeProtocol+this.youtubePreFix;

		if( this.supportsFlash() && mw.getConfig("forceIframe") != 1 ){
			// embed chromeless flash
			if(window['KeyValueParams']){
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid +
				"&amp&" + window['KeyValueParams'];
			}else{
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid ;
			}

			var classId = "";
			if( window.ActiveXObject ){
				classId= ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
			}

			var embedStr = 	'<object type="application/x-shockwave-flash" '+
							'id="' + this.pid + '" ' +
							'name="' + this.pid + '" ' + classId +
							'AllowScriptAccess="always" ' +
							'data="' + dataUrl + '" ' +
							'width="100%" height="100%">' +
							'<param name="movie" value="' + dataUrl+  '">' +
							'<param name="allowScriptAccess" value="always">' +
							'<param name="wmode" value="opaque">' +
							'<param name="bgcolor" value="#000000">' +
							'</object>';

			$('.persistentNativePlayer').replaceWith(embedStr);
		} else {
			// embed iframe ( native skin in iOS )
			$('.persistentNativePlayer').replaceWith('

');
			var tag = document.createElement('script');
			tag.src = "//www.youtube.com/iframe_api";
			var firstScriptTag = document.getElementsByTagName('script')[0];
			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
		}
	},
	setDuration: function(){

		//set duration only once
		if (this.duration == 0 && this.getPlayerElement().getDuration()){
			this.duration = this.getPlayerElement().getDuration();
			$(this).trigger('durationchange');
		}
	},
	onPlayerReady : function (event){

	},
	addBindings: function(){
	},
	supportsVolumeControl: function(){
		// if ipad no.
		return true;
	},
	getYouTubeId: function(){
		return this.getSrc().split('?')[1];
	},
	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	supportsFlash: function(){
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}
		var version = this.getFlashVersion().split(',').shift();
		if( version < 10 ){
			return false;
		} else {
			return true;
		}
	},
	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	getFlashVersion: function(){
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length){
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e){}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e){
						return '6,0,0';
					}
				}
			} catch(e){}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e){}
		return '0,0,0';
	 },
	/**
	 * javascript run post player embedding
	 */
	postEmbedActions : function(){
	},

	/**
	 * Bind a Player Function,
	 *
	 * Build a global callback to bind to "this" player instance:
	 *
	 * @param {String}
	 *            flash binding name
	 * @param {String}
	 *            function callback name
	 */
	bindPlayerFunction : function(bindName, methodName){
	},

	/**
	 * play method calls parent_play to update the interface
	 */
	play: function(){
		var _this = this;

		if(this.hasEnded){
				//handle replay
			}
		if( this.parent_play() ){
			if(_this.getPlayerElement())
			{
				_this.getPlayerElement().playVideo();
			}
		}
		this.monitor();
	},

	/**
	 * pause method calls parent_pause to update the interface
	 */
	pause: function(){
		var yt = this.getPlayerElement();
		yt.pauseVideo();
		this.parent_pause();
	},
	/**
	 * playerSwitchSource switches the player source working around a few bugs in browsers
	 *
	 * @param {object}
	 *            source Video Source object to switch to.
	 * @param {function}
	 *            switchCallback Function to call once the source has been switched
	 * @param {function}
	 *            doneCallback Function to call once the clip has completed playback
	 */
	playerSwitchSource: function( source, switchCallback, doneCallback ){

	},

	/**
	 * Issues a seek to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage of total stream length to seek to
	 */
	seek : function( percentage ){
		this.seeking = true;
		$( this ).trigger( 'seeking' );
		var yt = this.getPlayerElement();
		yt.seekTo( yt.getDuration() * percentage );
		this.controlBuilder.onSeek();
		//TODO check if there is a cleaner way to get the playback

	},

	/**
	 * Issues a volume update to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage to update volume to
	 */
	setPlayerElementVolume : function(percentage){
//		if ( this.getPlayerElement() && this.playerElement.sendNotification ){
//			this.playerElement.sendNotification('changeVolume', percentage);
//		}
		var yt = this.getPlayerElement();
		yt.setVolume(percentage*100);
	},

	/**
	 * function called by flash at set interval to update the playhead.
	 */
	onUpdatePlayhead : function( playheadValue ){
		this.time = playheadValue;
	},

	/**
	 * function called by flash when the total media size changes
	 */
	onBytesTotalChange : function(data, id){
		this.bytesTotal = data.newValue;
	},
	/**
	 * Get the embed player time
	 */
	getPlayerElementTime : function(){
		// update currentTime
		return this.getPlayerElement().getCurrentTime();
	},

	/**
	 * Get the embed fla object player Element
	 */
	getPlayerElement : function(){

		//IFRAME
		if( window['iframePlayer'] )
			return  window['iframePlayer']
		//Flash
		return $('#' + this.pid)[0];
	}
};

} )( mediaWiki, jQuery );
<commit_msg>remove hard coded id <commit_after>/*
 * The "kaltura player" embedPlayer interface for fallback h.264 and flv video format support
 * See http://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript for formating conventions
 */
( function( mw, $ ){ "use strict";

window['mwePlayerId'];
mw.EmbedPlayerYouTube = {

	//test comment for testing pull request

	// Instance name:
	instanceOf : 'youtube',

	bindPostfix: '.YouTube',
	//current playhead time
	time : 0,
	//current entry duration
	duration : 0,
	// A flag to store if the player has already been embed or not
	playerEmbedFlag: false,
	//Flag holdinng end state
	hasEnded: false,

	//the youtube entry id
	youtubeEntryId : "",

	//the youtube preFix
	//TODO grab from a configuration
	youtubePreFix : "//www.youtube.com/apiplayer?video_id=",
	youtubeProtocol : "http:",
	// List of supported features:
	supports : {
		'playHead' :  (mw.getConfig('previewMode') == null) ? true : false ,
		'pause' : true,
		'stop' : true,
		'timeDisplay' : true,
		'volumeControl' : true,
		'overlays' : true,
		'fullscreen' : (mw.getConfig('previewMode') == null) ? true : false
	},

	init: function(){
		var _this = this;
	},
	onPlayerStateChange : function (event){
		//delegate to window function
		window['onPlayerStateChange'](event);
	},

	registerGlobalCallbacks: function(){
		var _this = this;
		window['onPlayerStateChange'] = function( event ){
			var _this = $('#' + window['mwePlayerId'])[0];
			// clean up
			if( event.data || event.data == 0 || event.data ){
				event = event.data;
			}
			var stateName;
			// move to other method
			switch( event ){
				case -1:
					stateName = "unstarted";

				  break;
				case 0:
				case "0":
					stateName = "ended";
					this.hasEnded = true;
				  break;
				case 1:
					// hide the player container so that youtube click through work
					$('.mwEmbedPlayer').hide();
					//hide the poster
					$(".playerPoster").hide();
					$('.blackBoxHide').hide();
					_this.play();
					stateName = "playing";
					//$(this).hide();
					// update duraiton
					_this.setDuration();
					// trigger the seeked event only if this is seek and not in play
					if(_this.seeking){
						_this.seeking = false;
						$( _this ).trigger( 'seeked' );
						// update the playhead status
						_this.updatePlayheadStatus();
					}
				  break;
				case 2:
					stateName = "paused";
					_this.parent_pause();
				  break;
				case 3:
					stateName = "buffering";
				  break;
				case 4:
					stateName = "unbuffering";
					break;
				case 5:
					stateName = "video cued";
				  break;
			}

		};
		window['hidePlayer'] = function( event ){
			$('.playerPoster').before('

');
		}
		window['onError'] = function( event ){
			mw.log("Error! YouTubePlayer" ,2);
			$('#loadingSpinner_kaltura_player').append('
Error!');
			var errorMessage;
			if (event.data)
				event = event.data;
			switch( event ){
			case 2:
				errorMessage = "The request contains an invalid parameter value.";
				break;
			case 100:
				errorMessage = "The video requested was not found";
				break;
			case 101:
			case 150:
				errorMessage = "The owner of the requested video does not allow it to be played in embedded players";
				break;
			}
			$('#loadingSpinner_kaltura_player').append('
'+errorMessage);
			$(".playerPoster").hide();
			mw.log(errorMessage ,2);
		};
		//YOUTUBE IFRAME PLAYER READY (Not the Iframe - the player itself)
		window['onIframePlayerReady'] = function( event ){
			//autoplay
			$('#pid_kaltura_player').after('

');
			window['iframePlayer'] = event.target;
            //autoplay
            if(mw.getConfig('autoPlay')){
                  _this.play();
            }else{
                  window['hidePlayer']();
            }

		};
		// YOUTUBE FLASH PLAYER READY
		window['onYouTubePlayerReady'] = function( playerIdStr ){
			$('.ui-icon-image').hide()
			$('#pid_kaltura_player').after('

');
			var flashPlayer = $( '#' + playerIdStr )[0];
			flashPlayer.addEventListener("onStateChange", "onPlayerStateChange");
			flashPlayer.addEventListener("onError", "onError");
            //autoplay
            if(mw.getConfig('autoPlay')){
                  _this.play();
            }else{
                  window['hidePlayer']();
            }

		};
		// YOUTUBE IFRAME READY
		window['onYouTubeIframeAPIReady'] = function( playerIdStr ){
			$('.ui-icon-image').hide()
			//move to the other scope
            var embedPlayer = $('#' + window["pid"].replace( 'pid_', '' ) )[0];
            var playerVars;
            //basic configuration
            playerVars = {
                         controls: 0,
                         iv_load_policy:3,
                         rel: 0,
                         fs: 0,
                         wmode: 'opaque',
                         showinfo:0
            };

            if(window['KeyValueParams'])
            {
                  var kevarsArray = window['KeyValueParams'].split("&");
                  for(var i=0;i<kevarsArray.length;i++){
                         var kv = kevarsArray[i].split("=");
                         playerVars[kv[0]] = kv[1];
                  }

            }
            embedPlayer.playerElement = new YT.Player(pid,
                  {
                         height: '100%',
                         width: '100%',
                         videoId: window["youtubeEntryId"],
                         playerVars: playerVars,
                         events: {
                                'onReady': onIframePlayerReady,
                                'onError': onError,
                                'onStateChange': onPlayerStateChange
                         }
			});
		};
	},

	/*
	 * Write the Embed html to the target
	 */
	embedPlayerHTML : function(){
		this.registerGlobalCallbacks();
		if( this.playerEmbedFlag ){
			return ;
		}
		window['mwePlayerId'] = this.id;
		//handle fetching the youtubeId
		var metadata = this.evaluate('{mediaProxy.entryMetadata}');
		var entry = this.evaluate('{mediaProxy.entry}');
		//look for referenceId and then for custom data field YoutubeId
		if(entry.referenceId)
			this.youtubeEntryId = entry.referenceId;
		if(metadata.YoutubeId)
			this.youtubeEntryId = metadata.YoutubeId;

		if(this.youtubeEntryId.indexOf('http') > -1 || this.youtubeEntryId.indexOf('youtube') > -1  ){
			//found a full path - parse the entryId from it:
			var arr = this.youtubeEntryId.split("v=");
			var newEntryId = arr[1];
			if (newEntryId.indexOf("#") > -1)
				newEntryId = newEntryId.split("#")[0];
			if (newEntryId.indexOf("&") > -1)
				newEntryId = newEntryId.split("&")[0];
			this.youtubeEntryId = newEntryId;
		}

		if(metadata.KeyValueParams){
			window['KeyValueParams'] = metadata.KeyValueParams;
		}
		window['pid'] = this.pid;

		if(mw.getConfig("forceYoutubeEntry"))
		{
			this.youtubeEntryId=mw.getConfig("forceYoutubeEntry");
		}
		window["youtubeEntryId"] = this.youtubeEntryId;

		this.playerEmbedFlag = true;
		this.youtubeProtocol = location.protocol;
		this.youtubePreFix = this.youtubeProtocol+this.youtubePreFix;

		if( this.supportsFlash() && mw.getConfig("forceIframe") != 1 ){
			// embed chromeless flash
			if(window['KeyValueParams']){
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid +
				"&amp&" + window['KeyValueParams'];
			}else{
				var dataUrl = this.youtubePreFix + this.youtubeEntryId +'&showinfo=0&version=3&ampiv_load_policy=3&' +
				'enablejsapi=1&playerapiid=' + this.pid ;
			}

			var classId = "";
			if( window.ActiveXObject ){
				classId= ' classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" ';
			}

			var embedStr = 	'<object type="application/x-shockwave-flash" '+
							'id="' + this.pid + '" ' +
							'name="' + this.pid + '" ' + classId +
							'AllowScriptAccess="always" ' +
							'data="' + dataUrl + '" ' +
							'width="100%" height="100%">' +
							'<param name="movie" value="' + dataUrl+  '">' +
							'<param name="allowScriptAccess" value="always">' +
							'<param name="wmode" value="opaque">' +
							'<param name="bgcolor" value="#000000">' +
							'</object>';

			$('.persistentNativePlayer').replaceWith(embedStr);
		} else {
			// embed iframe ( native skin in iOS )
			$('.persistentNativePlayer').replaceWith('

');
			var tag = document.createElement('script');
			tag.src = "//www.youtube.com/iframe_api";
			var firstScriptTag = document.getElementsByTagName('script')[0];
			firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
		}
	},
	setDuration: function(){

		//set duration only once
		if (this.duration == 0 && this.getPlayerElement().getDuration()){
			this.duration = this.getPlayerElement().getDuration();
			$(this).trigger('durationchange');
		}
	},
	onPlayerReady : function (event){

	},
	addBindings: function(){
	},
	supportsVolumeControl: function(){
		// if ipad no.
		return true;
	},
	getYouTubeId: function(){
		return this.getSrc().split('?')[1];
	},
	/**
	 * If the browser supports flash
	 * @return {boolean} true or false if flash > 10 is supported.
	 */
	supportsFlash: function(){
		if( mw.getConfig('EmbedPlayer.DisableHTML5FlashFallback' ) ){
			return false;
		}
		var version = this.getFlashVersion().split(',').shift();
		if( version < 10 ){
			return false;
		} else {
			return true;
		}
	},
	/**
	 * Checks for flash version
	 * @return {string} flash version string
	 */
	getFlashVersion: function(){
		// navigator browsers:
		if (navigator.plugins && navigator.plugins.length){
			try {
				if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
					return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
				}
			} catch(e){}
		}
		// IE
		try {
			try {
				if( typeof ActiveXObject != 'undefined' ){
					// avoid fp6 minor version lookup issues
					// see: http://blog.deconcept.com/2006/01/11/getvariable-setvariable-crash-internet-explorer-flash-6/
					var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
					try {
						axo.AllowScriptAccess = 'always';
					} catch(e){
						return '6,0,0';
					}
				}
			} catch(e){}
			return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
		} catch(e){}
		return '0,0,0';
	 },
	/**
	 * javascript run post player embedding
	 */
	postEmbedActions : function(){
	},

	/**
	 * Bind a Player Function,
	 *
	 * Build a global callback to bind to "this" player instance:
	 *
	 * @param {String}
	 *            flash binding name
	 * @param {String}
	 *            function callback name
	 */
	bindPlayerFunction : function(bindName, methodName){
	},

	/**
	 * play method calls parent_play to update the interface
	 */
	play: function(){
		var _this = this;

		if(this.hasEnded){
				//handle replay
			}
		if( this.parent_play() ){
			if(_this.getPlayerElement())
			{
				_this.getPlayerElement().playVideo();
			}
		}
		this.monitor();
	},

	/**
	 * pause method calls parent_pause to update the interface
	 */
	pause: function(){
		var yt = this.getPlayerElement();
		yt.pauseVideo();
		this.parent_pause();
	},
	/**
	 * playerSwitchSource switches the player source working around a few bugs in browsers
	 *
	 * @param {object}
	 *            source Video Source object to switch to.
	 * @param {function}
	 *            switchCallback Function to call once the source has been switched
	 * @param {function}
	 *            doneCallback Function to call once the clip has completed playback
	 */
	playerSwitchSource: function( source, switchCallback, doneCallback ){

	},

	/**
	 * Issues a seek to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage of total stream length to seek to
	 */
	seek : function( percentage ){
		this.seeking = true;
		$( this ).trigger( 'seeking' );
		var yt = this.getPlayerElement();
		yt.seekTo( yt.getDuration() * percentage );
		this.controlBuilder.onSeek();
		//TODO check if there is a cleaner way to get the playback

	},

	/**
	 * Issues a volume update to the playerElement
	 *
	 * @param {Float}
	 *            percentage Percentage to update volume to
	 */
	setPlayerElementVolume : function(percentage){
//		if ( this.getPlayerElement() && this.playerElement.sendNotification ){
//			this.playerElement.sendNotification('changeVolume', percentage);
//		}
		var yt = this.getPlayerElement();
		yt.setVolume(percentage*100);
	},

	/**
	 * function called by flash at set interval to update the playhead.
	 */
	onUpdatePlayhead : function( playheadValue ){
		this.time = playheadValue;
	},

	/**
	 * function called by flash when the total media size changes
	 */
	onBytesTotalChange : function(data, id){
		this.bytesTotal = data.newValue;
	},
	/**
	 * Get the embed player time
	 */
	getPlayerElementTime : function(){
		// update currentTime
		return this.getPlayerElement().getCurrentTime();
	},

	/**
	 * Get the embed fla object player Element
	 */
	getPlayerElement : function(){

		//IFRAME
		if( window['iframePlayer'] )
			return  window['iframePlayer']
		//Flash
		return $('#' + this.pid)[0];
	}
};

} )( mediaWiki, jQuery );
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	{String} = require('sugar'),
	{validators} = require('@pzlr/build-core');

const
	$C = require('collection.js'),
	ss = require('snakeskin'),
	uuid = require('uuid');

const
	fs = require('fs'),
	path = require('path'),
	glob = require('glob'),
	findUp = require('find-up');

/**
 * Initializes Snakeskin
 *
 * @param {string} blocks - path to a block folder
 * @param {string} coreClient - path to the V4Fire core library
 */
module.exports = function ({blocks, coreClient}) {
	const
		blocksTree = {},
		components = `/**/@(${validators.blockTypeList.join('|')})-*.js`;

	const files = [].concat(
		glob.sync(path.join(coreClient, components)),
		glob.sync(path.join(blocks, components))
	);

	$C(files).forEach((el) => {
		const
			file = fs.readFileSync(el, {encoding: 'utf-8'});

		if (!/^export default class (.*?) extends (.*?) {/m.test(file)) {
			return;
		}

		const
			component = RegExp.$1,
			parent = RegExp.$2;

		const obj = blocksTree[component] = blocksTree[component] || {
			props: {},
			functional: /@component\s*\(\s*{\s*functional\s*:\s*true\s*}\s*\)/.test(file),
			parent
		};

		const
			propRgxp = /^(\t@(?:field|abstract)[\s\S]+?\)*\n+)?\t([\w$]+)\s*:\s*[ \w|&$?()[\]{}<>'"`:.]+?\s*(?:=|;$)/gm;

		let s;
		while ((s = propRgxp.exec(file))) {
			if (!s[1]) {
				obj.props[s[2]] = true;
			}
		}
	});

	$C(blocksTree).forEach((el, key, data) => {
		if (el.parent && data[el.parent]) {
			Object.setPrototypeOf(el.props, data[el.parent].props);
		}
	});

	const bind = {
		bind: [
			(o) => o.getVar('$attrs'),
			'typeof rootTag !== "undefined" ? rootTag : undefined'
		]
	};

	ss.importFilters({
		vueComp,
		vueTag: ss.setFilterParams(vueTag, bind),
		bem2vue: ss.setFilterParams(bem2vue, bind),
		b: ss.setFilterParams(b, {bind: ['__dirname']})
	});

	function b(url, cwd) {
		const
			end = /\.e?ss$/.test(url) ? '' : '/',
			ends = [];

		if (end) {
			const
				basename = path.basename(url);

			if (glob.hasMagic(basename)) {
				ends.push(basename);
			}

			ends.push('main.ss', 'index.ss');

		} else {
			ends.push('');
		}

		const urls = [
			blocks,
			findUp.sync('src', {cwd}),
			coreClient
		];

		for (let i = 0; i < urls.length; i++) {
			for (let j = 0; j < ends.length; j++) {
				const
					fullPath = path.join(urls[i], url, ends[j]);

				if (glob.sync(fullPath)) {
					return fullPath;
				}
			}
		}

		return url + end;
	}

	function vueComp({name, attrs}) {
		$C(attrs).forEach((el, key) => {
			if (!/^(:|@|v-)/.test(key)) {
				return;
			}

			const
				tmp = String.dasherize(key);

			if (tmp !== key) {
				delete attrs[key];
				attrs[tmp] = el;
			}
		});

		let
			isSync = attrs['v-sync'];

		const
			isAsync = attrs['v-async'],
			isAsyncBack = attrs['v-async-back'];

		if (attrs['v-for']) {
			if (/^\s*([\w$]+)(\s+(?:in|of)\s+.*)$/.test(attrs['v-for'].join(' '))) {
				attrs['v-for'] = [`(${RegExp.$1}, i)${RegExp.$2}`];
			}
		}

		delete attrs['v-sync'];
		delete attrs['v-async'];
		delete attrs['v-async-back'];

		$C(attrs).forEach((el, key) => {
			if (key.slice(0, 2) === ':-') {
				attrs[`:data-${key.slice(2)}`] = el;
				delete attrs[key];

			} else if (key === ':key') {
				const
					parts = el.join('').split(/\s*,\s*/),
					val = attrs[key] = parts.slice(-1);

				$C(parts.slice(0, -1)).forEach((key) => {
					if (key.slice(0, 2) === ':-') {
						attrs[`:data-${key.slice(2)}`] = val;

					} else {
						attrs[key] = val;
					}
				});
			}
		});

		if (name === 'component' || validators.blockName(name)) {
			let componentName;
			if (attrs[':instance-of']) {
				componentName = attrs[':instance-of'][0];
				delete attrs[':instance-of'];

			} else {
				componentName = name === 'component' ? 'iBlock' : String.camelize(name, false);
			}

			const
				c = blocksTree[componentName];

			if (!isAsync && !isAsyncBack && c && c.functional) {
				isSync = true;
			}

			$C(attrs).forEach((el, key) => {
				if (key[0] !== ':') {
					return;
				}

				const
					base = key.slice(1),
					prop = `${base}Prop`;

				if (c && !c.props[base] && c.props[prop]) {
					attrs[`:${String.dasherize(prop)}`] = el;
					delete attrs[key];
				}
			});

			if (!attrs[':mods-prop']) {
				attrs[':mods-prop'] = ['provideMods()'];
			}
		}

		if (!isSync && !attrs.ref && !attrs[':ref'] && (isAsync || isAsyncBack)) {
			const
				id = `'${uuid()}' + i`,
				p = isAsyncBack ? 'Back' : '',
				key = attrs['v-else'] ? 'v-else-if' : attrs['v-else-if'] ? 'v-else-if' : 'v-if';

			attrs[key] = attachVIf(
				(attrs[key] || []).concat(`async${p}Components[regAsync${p}Component(${id}, '${name}')]`),
				isAsyncBack ? '||' : '&&'
			);

			delete attrs['v-else'];
		}
	}

	function vueTag(tag, attrs, rootTag) {
		if (/^a:void$/.test(tag)) {
			attrs.href = ['javascript:void(0)'];
			tag = 'a';

		} else if (/^button:a$/.test(tag)) {
			attrs.type = ['button'];
			attrs.class = attachClass((attrs.class || []).concat('a'));
			tag = 'button';

		} else if (tag === '_') {
			tag = rootTag;
		}

		return tag;
	}

	function attachVIf(arr, op) {
		const
			join = arr.join;

		arr.join = function () {
			return join.call(this, op);
		};

		return arr;
	}

	function bem2vue(block, attrs, rootTag, val) {
		const
			tmp = attrs[':class'] = attrs[':class'] || [];

		if (!$C(tmp).includes('blockId')) {
			attrs[':class'] = attachClass(tmp.concat('blockId', `classes['${val.replace(/^_+/, '')}']`));
		}

		return block + val;
	}

	function attachClass(arr) {
		const
			join = arr.join;

		arr.join = function () {
			if (this.length < 2) {
				return join.call(this);
			}

			return `[${join.call(this, ',')}]`;
		};

		return arr;
	}
};
<commit_msg>:wrench:<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

const
	{String} = require('sugar'),
	{validators} = require('@pzlr/build-core');

const
	$C = require('collection.js'),
	ss = require('snakeskin'),
	uuid = require('uuid');

const
	fs = require('fs'),
	path = require('path'),
	glob = require('glob'),
	findUp = require('find-up');

/**
 * Initializes Snakeskin
 *
 * @param {string} blocks - path to a block folder
 * @param {string} coreClient - path to the V4Fire core library
 */
module.exports = function ({blocks, coreClient}) {
	const
		blocksTree = {},
		components = `/**/@(${validators.blockTypeList.join('|')})-*.js`;

	const files = [].concat(
		glob.sync(path.join(coreClient, components)),
		glob.sync(path.join(blocks, components))
	);

	$C(files).forEach((el) => {
		const
			file = fs.readFileSync(el, {encoding: 'utf-8'});

		if (!/^export default class (.*?) extends (.*?) {/m.test(file)) {
			return;
		}

		const
			component = RegExp.$1,
			parent = RegExp.$2;

		const obj = blocksTree[component] = blocksTree[component] || {
			props: {},
			functional: /@component\s*\(\s*{\s*functional\s*:\s*true\s*}\s*\)/.test(file),
			parent
		};

		const
			propRgxp = /^(\t@(?:field|abstract)[\s\S]+?\)*\n+)?\t([\w$]+)\s*:\s*[ \w|&$?()[\]{}<>'"`:.]+?\s*(?:=|;$)/gm;

		let s;
		while ((s = propRgxp.exec(file))) {
			if (!s[1]) {
				obj.props[s[2]] = true;
			}
		}
	});

	$C(blocksTree).forEach((el, key, data) => {
		if (el.parent && data[el.parent]) {
			Object.setPrototypeOf(el.props, data[el.parent].props);
		}
	});

	const bind = {
		bind: [
			(o) => o.getVar('$attrs'),
			'typeof rootTag !== "undefined" ? rootTag : undefined'
		]
	};

	ss.importFilters({
		vueComp,
		vueTag: ss.setFilterParams(vueTag, bind),
		bem2vue: ss.setFilterParams(bem2vue, bind),
		b: ss.setFilterParams(b, {bind: ['__dirname']})
	});

	function b(url, cwd) {
		const
			end = /\.e?ss$/.test(url) ? '' : '/',
			ends = [];

		if (end) {
			const
				basename = path.basename(url);

			if (!glob.hasMagic(basename)) {
				ends.push(basename);
			}

			ends.push('main.ss', 'index.ss');

		} else {
			ends.push('');
		}

		const urls = [
			blocks,
			findUp.sync('src', {cwd}),
			coreClient
		];

		for (let i = 0; i < urls.length; i++) {
			for (let j = 0; j < ends.length; j++) {
				const
					fullPath = path.join(urls[i], url, ends[j]);

				if (glob.sync(fullPath)) {
					return fullPath;
				}
			}
		}

		return url + end;
	}

	function vueComp({name, attrs}) {
		$C(attrs).forEach((el, key) => {
			if (!/^(:|@|v-)/.test(key)) {
				return;
			}

			const
				tmp = String.dasherize(key);

			if (tmp !== key) {
				delete attrs[key];
				attrs[tmp] = el;
			}
		});

		let
			isSync = attrs['v-sync'];

		const
			isAsync = attrs['v-async'],
			isAsyncBack = attrs['v-async-back'];

		if (attrs['v-for']) {
			if (/^\s*([\w$]+)(\s+(?:in|of)\s+.*)$/.test(attrs['v-for'].join(' '))) {
				attrs['v-for'] = [`(${RegExp.$1}, i)${RegExp.$2}`];
			}
		}

		delete attrs['v-sync'];
		delete attrs['v-async'];
		delete attrs['v-async-back'];

		$C(attrs).forEach((el, key) => {
			if (key.slice(0, 2) === ':-') {
				attrs[`:data-${key.slice(2)}`] = el;
				delete attrs[key];

			} else if (key === ':key') {
				const
					parts = el.join('').split(/\s*,\s*/),
					val = attrs[key] = parts.slice(-1);

				$C(parts.slice(0, -1)).forEach((key) => {
					if (key.slice(0, 2) === ':-') {
						attrs[`:data-${key.slice(2)}`] = val;

					} else {
						attrs[key] = val;
					}
				});
			}
		});

		if (name === 'component' || validators.blockName(name)) {
			let componentName;
			if (attrs[':instance-of']) {
				componentName = attrs[':instance-of'][0];
				delete attrs[':instance-of'];

			} else {
				componentName = name === 'component' ? 'iBlock' : String.camelize(name, false);
			}

			const
				c = blocksTree[componentName];

			if (!isAsync && !isAsyncBack && c && c.functional) {
				isSync = true;
			}

			$C(attrs).forEach((el, key) => {
				if (key[0] !== ':') {
					return;
				}

				const
					base = key.slice(1),
					prop = `${base}Prop`;

				if (c && !c.props[base] && c.props[prop]) {
					attrs[`:${String.dasherize(prop)}`] = el;
					delete attrs[key];
				}
			});

			if (!attrs[':mods-prop']) {
				attrs[':mods-prop'] = ['provideMods()'];
			}
		}

		if (!isSync && !attrs.ref && !attrs[':ref'] && (isAsync || isAsyncBack)) {
			const
				id = `'${uuid()}' + i`,
				p = isAsyncBack ? 'Back' : '',
				key = attrs['v-else'] ? 'v-else-if' : attrs['v-else-if'] ? 'v-else-if' : 'v-if';

			attrs[key] = attachVIf(
				(attrs[key] || []).concat(`async${p}Components[regAsync${p}Component(${id}, '${name}')]`),
				isAsyncBack ? '||' : '&&'
			);

			delete attrs['v-else'];
		}
	}

	function vueTag(tag, attrs, rootTag) {
		if (/^a:void$/.test(tag)) {
			attrs.href = ['javascript:void(0)'];
			tag = 'a';

		} else if (/^button:a$/.test(tag)) {
			attrs.type = ['button'];
			attrs.class = attachClass((attrs.class || []).concat('a'));
			tag = 'button';

		} else if (tag === '_') {
			tag = rootTag;
		}

		return tag;
	}

	function attachVIf(arr, op) {
		const
			join = arr.join;

		arr.join = function () {
			return join.call(this, op);
		};

		return arr;
	}

	function bem2vue(block, attrs, rootTag, val) {
		const
			tmp = attrs[':class'] = attrs[':class'] || [];

		if (!$C(tmp).includes('blockId')) {
			attrs[':class'] = attachClass(tmp.concat('blockId', `classes['${val.replace(/^_+/, '')}']`));
		}

		return block + val;
	}

	function attachClass(arr) {
		const
			join = arr.join;

		arr.join = function () {
			if (this.length < 2) {
				return join.call(this);
			}

			return `[${join.call(this, ',')}]`;
		};

		return arr;
	}
};
<|endoftext|>


<commit_before>/**
* EmbedPlayer loader
*/
/**
* Default player module configuration
*/

mw.IA =
{
  VIDEO_WIDTH:640,
  VIDEO_HEIGHT:480,
  VIDEO_PLAYLIST_HEIGHT:80,

  video:true, //false means we are audio

  css:function(str)
  {
    var obj = document.createElement('style');
    obj.setAttribute('type', 'text/css');
    if (obj.styleSheet)
      obj.styleSheet.cssText = str; //MSIE
    else
      obj.appendChild(document.createTextNode(str)); // other browsers

    var headobj = document.getElementsByTagName("head")[0];
    headobj.appendChild(obj);
  },

  argin:function(theArgName, ary)
  {
    r = '';
    for (var i=0; i < ary.length; i++)
    {
      if (ary[i].slice(0,ary[i].indexOf('=')) == theArgName)
      {
        r = ary[i].slice(ary[i].indexOf('=')+1);
        break;
      }
    }
    return (r.length > 0 ? unescape(r).split(',') : '');
  },

  // parse a CGI arg
  arg:function(theArgName)
  {
    var ary = location.search.slice(1).split('&');
    mw.IA.log(ary);
    return this.argin(theArgName, ary);
  },

  // try to parse the identifier from the video and make the lower right icon
  // then go to the item's /details/ page
  detailsLink:function()
  {
    if (typeof(location.pathname)!='undefined'  &&
        location.pathname.length>0  &&
        location.pathname.match(/^\/details\//))
    {
      return '/details/'+location.pathname.replace(/^\/details\/([^\/]+).*$/,
                                                   '$1');
    }
    if (typeof(location.pathname)!='undefined'  &&
        location.pathname.length>0  &&
        location.pathname.match(/^\/embed\//))
    {
      return '/details/'+location.pathname.replace(/^\/embed\/([^\/]+).*$/,
                                                   '$1');
    }

    if (typeof(document.getElementsByTagName)!='undefined')
    {
      var els = document.getElementsByTagName('object');
      if (els  &&  els.length)
      {
        var i=0;
        for (i=0; i < els.length; i++)
        {
          var el = els[i];
          if (typeof(el.data)!='undefined')
          {
            var mat = el.data.match(/\.archive.org\/download\/([^\/]+)/);
            if (typeof(mat)!='undefined'  &&  mat  &&  mat.length>1)
            {
              return '/details/' + mat[1];
            }
          }
        }
      }
    }

    return '';
  },

  embedUrl:function()
  {
    return ('http://www.archive.org/embed/' +
            mw.IA.detailsLink().replace(/\/details\//,''));
  },

  embedCode:function()
  {
    return ('<iframe src="' +
            mw.escapeQuotesHTML( mw.IA.embedUrl() ) + '" ' +
            'width="' + mw.IA.VIDEO_WIDTH +'" ' +
            'height="' + mw.IA.VIDEO_HEIGHT + '" ' +
            'frameborder="0" ' +
            '>&lt/iframe>');
  },

  // Set up so that:
  //   - when "click to play" clicked, resize video window and playlist
  //   - we advance to the next clip (when 2+ present)
  newEmbedPlayerEvent:function(arg)
  {
    mw.IA.log('newEmbedPlayerEvent');

    if (typeof($('#iframeVidso').get(0)) != 'undefined')
    {
      mw.setConfig( {
        'EmbedPlayer.EnabledOptionsMenuItems':
        ['playerSelect','share','aboutPlayerLibrary']
      });
    }

    // Now put a nice looking "track number" in front of each playlist entry title
    $('div.playlistItem span.clipTitle').html(function(i,html) {
      return html.replace(/^(\d+)(.*)/, '$1$2');
    });

    var player = $('#mwplayer');
    if (!player)
      return;

    if (typeof(mw.IA.mrss)!='undefined')
    {
      if (mw.IA.video)
      {
        mw.IA.log('this is /details/ video!');
        mw.IA.video = true;

        player.unbind('play').bind('play', mw.IA.resize);

        // player.bind('pause', mw.IA.pause); //xxx hash not quite ready yet
        if (!mw.isMobileDevice())
        {
          player.bind('onCloseFullScreen', function(){ setTimeout(function() {
            mw.IA.resize(); }, 500); });
        }
      }
      else
      {
        mw.IA.log('this is /details/ audio!');
      }
    }
  },

  pause:function()
  {
    mw.IA.log('paused');

    // for hitting play:
    // location.hash = '#' + group['ORIG']; //xxxx hash not quite ready yet

    location.hash = '#' + // [get ORIG video file from playlist item and then matched back thru mrss variable etc.?]  +
      '/start=' + Math.round($('#mwplayer').get(0).currentTime * 10) / 10;
  },

  resize:function()
  {
    if (mw.isMobileDevice())
      return;

    if (!mw.IA.video)
      return;

    mw.IA.log('resize');

    var av=$('div.mv-player video, div.mv-player object, div.mv-player embed').parent().get(0);

    if (typeof(av)=='undefined'  &&  $('img.playerPoster').length > 0)
    {
      var wd = mw.IA.VIDEO_WIDTH / 2;
      var ht = mw.IA.VIDEO_HEIGHT / 2;
    }
    else
    {
      var wd = mw.IA.VIDEO_WIDTH;
      var ht = mw.IA.VIDEO_HEIGHT;

      if (typeof(av)!='undefined')
        av.resizePlayer({'width': wd, 'height':ht}, true);
    }

    $('#mwplayer_videolist').css('top', ht);

    $('#avplaydiv').css('width', wd);

    $('#mwplayer').css('width',  wd);
    $('#mwplayer').css('height', ht + mw.IA.VIDEO_PLAYLIST_HEIGHT);
  },

  log:function(str)
  {
    if ( typeof console == 'undefined' )
      return;

    if (str==mw.IA.mrss)
    {
      console.dirxml($j.parseXML(unescape(mw.IA.mrss).replace(/\+/g,' ')));
      return;
    }
    mw.log('      ---IA------------------------------>   '+str);
  },

  setup: function() {

    mw.IA.css("\n\
audio { z-index:666 !important; position:absolute !important; bottom:0px !important; } \n\
\n\
\n\
\n\
div#mwplayer_videolist { bottom:0px !important; right:0px !important; }\n\
div.playlistItem {\n\
  font-family:Lucida Grande;\n\
  margin:0px 5px 0px 5px !important;\n\
  padding:2px !important;\n\
}\n\
div.maudio div.playlistItem { padding:0px !important; }\n\
div.playlist-title { display:none; }\n\
div.playlistItem img { display:none; }\n\
div.playlistItem span.clipTitle     { padding-left:15px; }\n\
div.playlistItem span.tn            { display:inline-block; width:25px; text-align:right; padding-right:5px; border-right:1px solid gray; }\n\
div.playlistItem div.clipDuration  { padding-right:20px; padding-top:1px; }\n\
div.movies div.playlistItem div.clipDuration  { display:none; }\n\
div.ui-state-active {\n\
  background-image:url(/images/orange_arrow.gif) !important;\n\
  background-position:10px 2px !important;\n\
  background-repeat:no-repeat !important;\n\
}\n\
\n\
.archive-icon {\n\
background-image:url('http://www.archive.org/images/logo-mw.png') !important;\n\
background-repeat:no-repeat;\n\
display: block;\n\
height: 12px;\n\
width: 12px;\n\
margin-left: 3px !important;\n\
}\n\
\n\
div.control-bar { -moz-border-radius:6px; -webkit-border-radius:6px; -khtml-border-radius:6px; border-radius:6px; }\n\
\n\
\n\
\n\
div.movies div.media-rss-video-list { background-image:url(/logos/hires/ia-tight-60x60-one-third-opacity.png); background-position:bottom; background-repeat:no-repeat; }\n\
div.maudio div.media-rss-video-list { background-image:url(/logos/hires/ia-tight-240x240-one-third-opacity.png); background-position:bottom; background-repeat:no-repeat; }\n\
div.maudio div.fullscreen-btn { display:none !important; }\n\
div.maudio img.playerPoster   { display:none; } \n\
div.maudio div.play-btn-large { display:none; } \n\
div.maudio div.media-rss-video-player { height:26px !important; } \n\
div.maudio div.mrss_mwplayer_0 { height:26px !important; } \n\
div.maudio div.mv-player  { height:26px !important; } \n\
div.maudio div.control-bar { display:block !important; } \n\
\n\
\n\
\n\
\n\
div.overlay-content { background-color:#666 !important; } \n\
div.overlay-content div h2 { background-color:transparent; }\n\
div.overlay-content        {\n\
  padding-top:0px !important; \n\
  border: 1px solid #666; \n\
  -moz-border-radius: 10px;\n\
  -webkit-border-radius:10px;\n\
  -khtml-border-radius:10px;\n\
  border-radius: 10px;\n\
}\n\
.mv-player .overlay-win textarea { height:60px !important; }\n\
");

    mw.setConfig( {
        // We want our video player to attribute something...
        "EmbedPlayer.AttributionButton" : true,

        'Mw.UserPreferenceExpireDays' : 90,

        // Our attribution button
        'EmbedPlayer.AttributionButton' : {
          'title' : 'Internet Archive',
          'href' : 'http://www.archive.org' + mw.IA.detailsLink(),
          'class' : 'archive-icon'
        },

        'imagesPath' : 'http://www/archive.org/images/', //xxxxxxx not working yet

        'Playlist.TitleLength': 35
      });

    if (!mw.isMobileDevice())
      mw.setConfig({'Playlist.ShowScrollButtons':false});

    // NOTE: keep this outside "mw.ready()" so that "click-to-play" does indeed
    // cause the newEmbedPlayerEvent() call
    $( mw ).bind('newEmbedPlayerEvent', mw.IA.newEmbedPlayerEvent);

    mw.ready(function(){
        var hash = unescape(location.hash);
        mw.IA.log("IA Player says mw.ready()" + hash);

        var star = (mw.IA.arg('start') ? parseFloat(mw.IA.arg('start')) : 0);
        if (!star)
        {
          // look for: /details/drake_saga1_shots/MVI_3986.AVI/start=13
          var a = location.pathname.split('/');
          star=(mw.IA.argin('start',a) ? parseFloat(mw.IA.argin('start',a)) : 0);
        }
        if (!star)
        {
          // look for: /details/drake_saga1_shots/MVI_3986.AVI#start=13
          var a = location.hash.slice(1).split('/');
          star=(mw.IA.argin('start',a) ? parseFloat(mw.IA.argin('start',a)) : 0);
        }
        if (star)
        {
          mw.IA.resize();
          var jplay = $('#mwplayer').get(0);
          var dura = jplay.duration;
          mw.IA.log(star+'s of '+dura+'s');

          jplay.currentTime = star;
          jplay.play();
        }
      });
  }
};

mw.IA.setup();
<commit_msg>minor bump to new playlist CSS<commit_after>/**
* EmbedPlayer loader
*/
/**
* Default player module configuration
*/

mw.IA =
{
  VIDEO_WIDTH:640,
  VIDEO_HEIGHT:480,
  VIDEO_PLAYLIST_HEIGHT:80,

  video:true, //false means we are audio

  css:function(str)
  {
    var obj = document.createElement('style');
    obj.setAttribute('type', 'text/css');
    if (obj.styleSheet)
      obj.styleSheet.cssText = str; //MSIE
    else
      obj.appendChild(document.createTextNode(str)); // other browsers

    var headobj = document.getElementsByTagName("head")[0];
    headobj.appendChild(obj);
  },

  argin:function(theArgName, ary)
  {
    r = '';
    for (var i=0; i < ary.length; i++)
    {
      if (ary[i].slice(0,ary[i].indexOf('=')) == theArgName)
      {
        r = ary[i].slice(ary[i].indexOf('=')+1);
        break;
      }
    }
    return (r.length > 0 ? unescape(r).split(',') : '');
  },

  // parse a CGI arg
  arg:function(theArgName)
  {
    var ary = location.search.slice(1).split('&');
    mw.IA.log(ary);
    return this.argin(theArgName, ary);
  },

  // try to parse the identifier from the video and make the lower right icon
  // then go to the item's /details/ page
  detailsLink:function()
  {
    if (typeof(location.pathname)!='undefined'  &&
        location.pathname.length>0  &&
        location.pathname.match(/^\/details\//))
    {
      return '/details/'+location.pathname.replace(/^\/details\/([^\/]+).*$/,
                                                   '$1');
    }
    if (typeof(location.pathname)!='undefined'  &&
        location.pathname.length>0  &&
        location.pathname.match(/^\/embed\//))
    {
      return '/details/'+location.pathname.replace(/^\/embed\/([^\/]+).*$/,
                                                   '$1');
    }

    if (typeof(document.getElementsByTagName)!='undefined')
    {
      var els = document.getElementsByTagName('object');
      if (els  &&  els.length)
      {
        var i=0;
        for (i=0; i < els.length; i++)
        {
          var el = els[i];
          if (typeof(el.data)!='undefined')
          {
            var mat = el.data.match(/\.archive.org\/download\/([^\/]+)/);
            if (typeof(mat)!='undefined'  &&  mat  &&  mat.length>1)
            {
              return '/details/' + mat[1];
            }
          }
        }
      }
    }

    return '';
  },

  embedUrl:function()
  {
    return ('http://www.archive.org/embed/' +
            mw.IA.detailsLink().replace(/\/details\//,''));
  },

  embedCode:function()
  {
    return ('<iframe src="' +
            mw.escapeQuotesHTML( mw.IA.embedUrl() ) + '" ' +
            'width="' + mw.IA.VIDEO_WIDTH +'" ' +
            'height="' + mw.IA.VIDEO_HEIGHT + '" ' +
            'frameborder="0" ' +
            '>&lt/iframe>');
  },

  // Set up so that:
  //   - when "click to play" clicked, resize video window and playlist
  //   - we advance to the next clip (when 2+ present)
  newEmbedPlayerEvent:function(arg)
  {
    mw.IA.log('newEmbedPlayerEvent');

    if (typeof($('#iframeVidso').get(0)) != 'undefined')
    {
      mw.setConfig( {
        'EmbedPlayer.EnabledOptionsMenuItems':
        ['playerSelect','share','aboutPlayerLibrary']
      });
    }

    // Now put a nice looking "track number" in front of each playlist entry title
    $('div.playlistItem span.clipTitle').html(function(i,html) {
      return html.replace(/^(\d+)(.*)/, '$1$2');
    });

    var player = $('#mwplayer');
    if (!player)
      return;

    if (typeof(mw.IA.mrss)!='undefined')
    {
      if (mw.IA.video)
      {
        mw.IA.log('this is /details/ video!');
        mw.IA.video = true;

        player.unbind('play').bind('play', mw.IA.resize);

        // player.bind('pause', mw.IA.pause); //xxx hash not quite ready yet
        if (!mw.isMobileDevice())
        {
          player.bind('onCloseFullScreen', function(){ setTimeout(function() {
            mw.IA.resize(); }, 500); });
        }
      }
      else
      {
        mw.IA.log('this is /details/ audio!');
      }
    }
  },

  pause:function()
  {
    mw.IA.log('paused');

    // for hitting play:
    // location.hash = '#' + group['ORIG']; //xxxx hash not quite ready yet

    location.hash = '#' + // [get ORIG video file from playlist item and then matched back thru mrss variable etc.?]  +
      '/start=' + Math.round($('#mwplayer').get(0).currentTime * 10) / 10;
  },

  resize:function()
  {
    if (mw.isMobileDevice())
      return;

    if (!mw.IA.video)
      return;

    mw.IA.log('resize');

    var av=$('div.mv-player video, div.mv-player object, div.mv-player embed').parent().get(0);

    if (typeof(av)=='undefined'  &&  $('img.playerPoster').length > 0)
    {
      var wd = mw.IA.VIDEO_WIDTH / 2;
      var ht = mw.IA.VIDEO_HEIGHT / 2;
    }
    else
    {
      var wd = mw.IA.VIDEO_WIDTH;
      var ht = mw.IA.VIDEO_HEIGHT;

      if (typeof(av)!='undefined')
        av.resizePlayer({'width': wd, 'height':ht}, true);
    }

    $('#mwplayer_videolist').css('top', ht);

    $('#avplaydiv').css('width', wd);

    $('#mwplayer').css('width',  wd);
    $('#mwplayer').css('height', ht + mw.IA.VIDEO_PLAYLIST_HEIGHT);
  },

  log:function(str)
  {
    if ( typeof console == 'undefined' )
      return;

    if (str==mw.IA.mrss)
    {
      console.dirxml($j.parseXML(unescape(mw.IA.mrss).replace(/\+/g,' ')));
      return;
    }
    mw.log('      ---IA------------------------------>   '+str);
  },

  setup: function() {

    mw.IA.css("\n\
audio { z-index:666 !important; position:absolute !important; bottom:0px !important; } \n\
\n\
\n\
\n\
div#mwplayer_videolist { bottom:0px !important; right:0px !important; }\n\
div.playlistItem {\n\
  font-family:Lucida Grande;\n\
  margin:0px 5px 0px 5px !important;\n\
}\n\
div.maudio div.playlistItem { padding:0px !important; }\n\
div.playlist-title { display:none; }\n\
div.playlistItem img { display:none; }\n\
div.playlistItem span.clipTitle     { padding-left:15px; }\n\
div.playlistItem span.tn            { display:inline-block; width:25px; text-align:right; padding-right:5px; border-right:1px solid gray; }\n\
div.playlistItem div.clipDuration  { padding-right:20px; padding-top:1px; }\n\
div.movies div.playlistItem div.clipDuration  { display:none; }\n\
div.ui-state-active {\n\
  background-image:url(/images/orange_arrow.gif) !important;\n\
  background-position:10px 2px !important;\n\
  background-repeat:no-repeat !important;\n\
}\n\
\n\
.archive-icon {\n\
background-image:url('http://www.archive.org/images/logo-mw.png') !important;\n\
background-repeat:no-repeat;\n\
display: block;\n\
height: 12px;\n\
width: 12px;\n\
margin-left: 3px !important;\n\
}\n\
\n\
div.control-bar { -moz-border-radius:6px; -webkit-border-radius:6px; -khtml-border-radius:6px; border-radius:6px; }\n\
\n\
\n\
\n\
div.movies div.media-rss-video-list { background-image:url(/logos/hires/ia-tight-60x60-one-third-opacity.png); background-position:bottom; background-repeat:no-repeat; }\n\
div.maudio div.media-rss-video-list { background-image:url(/logos/hires/ia-tight-240x240-one-third-opacity.png); background-position:bottom; background-repeat:no-repeat; }\n\
div.maudio div.fullscreen-btn { display:none !important; }\n\
div.maudio img.playerPoster   { display:none; } \n\
div.maudio div.play-btn-large { display:none; } \n\
div.maudio div.media-rss-video-player { height:26px !important; } \n\
div.maudio div.mrss_mwplayer_0 { height:26px !important; } \n\
div.maudio div.mv-player  { height:26px !important; } \n\
div.maudio div.control-bar { display:block !important; } \n\
\n\
\n\
\n\
\n\
div.overlay-content { background-color:#666 !important; } \n\
div.overlay-content div h2 { background-color:transparent; }\n\
div.overlay-content        {\n\
  padding-top:0px !important; \n\
  border: 1px solid #666; \n\
  -moz-border-radius: 10px;\n\
  -webkit-border-radius:10px;\n\
  -khtml-border-radius:10px;\n\
  border-radius: 10px;\n\
}\n\
.mv-player .overlay-win textarea { height:60px !important; }\n\
");

    mw.setConfig( {
        // We want our video player to attribute something...
        "EmbedPlayer.AttributionButton" : true,

        'Mw.UserPreferenceExpireDays' : 90,

        // Our attribution button
        'EmbedPlayer.AttributionButton' : {
          'title' : 'Internet Archive',
          'href' : 'http://www.archive.org' + mw.IA.detailsLink(),
          'class' : 'archive-icon'
        },

        'imagesPath' : 'http://www/archive.org/images/', //xxxxxxx not working yet

        'Playlist.TitleLength': 35
      });

    if (!mw.isMobileDevice())
      mw.setConfig({'Playlist.ShowScrollButtons':false});

    // NOTE: keep this outside "mw.ready()" so that "click-to-play" does indeed
    // cause the newEmbedPlayerEvent() call
    $( mw ).bind('newEmbedPlayerEvent', mw.IA.newEmbedPlayerEvent);

    mw.ready(function(){
        var hash = unescape(location.hash);
        mw.IA.log("IA Player says mw.ready()" + hash);

        var star = (mw.IA.arg('start') ? parseFloat(mw.IA.arg('start')) : 0);
        if (!star)
        {
          // look for: /details/drake_saga1_shots/MVI_3986.AVI/start=13
          var a = location.pathname.split('/');
          star=(mw.IA.argin('start',a) ? parseFloat(mw.IA.argin('start',a)) : 0);
        }
        if (!star)
        {
          // look for: /details/drake_saga1_shots/MVI_3986.AVI#start=13
          var a = location.hash.slice(1).split('/');
          star=(mw.IA.argin('start',a) ? parseFloat(mw.IA.argin('start',a)) : 0);
        }
        if (star)
        {
          mw.IA.resize();
          var jplay = $('#mwplayer').get(0);
          var dura = jplay.duration;
          mw.IA.log(star+'s of '+dura+'s');

          jplay.currentTime = star;
          jplay.play();
        }
      });
  }
};

mw.IA.setup();
<|endoftext|>


<commit_before>import Head from 'next/head';
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import uniqBy from 'lodash/uniqBy';

import useRouter from 'utils/router';
import { decodeQueryParams } from 'utils/url';
import { parseGadm36Id } from 'utils/gadm';
import { parseStringWithVars } from 'utils/strings';

import { getLocationData } from 'services/location';
import {
  // getCountriesProvider,
  getRegionsProvider,
  getSubRegionsProvider,
  getCategorisedCountries,
  getCountryLinksSerialized,
} from 'services/country';

import PageLayout from 'wrappers/page';
import Dashboards from 'layouts/dashboards';

import DashboardsUrlProvider from 'providers/dashboards-url-provider';

import { setCountriesSSR } from 'providers/country-data-provider/actions';

import {
  getSentenceData,
  parseSentence,
  handleSSRLocationObjects,
} from 'services/sentences';

import { setGeodescriberSSR } from 'providers/geodescriber-provider/actions';
import { setMapSettings } from 'components/map/actions';
import { setModalMetaSettings } from 'components/modals/meta/actions';
import { setDashboardPrompts } from 'components/prompts/dashboard-prompts/actions';

import {
  setWidgetsSettings,
  setWidgetsCategory,
  setShowMap,
  setActiveWidget,
} from 'components/widgets/actions';

const notFoundProps = {
  error: 404,
  title: 'Dashboard Not Found | Global Forest Watch',
  errorTitle: 'Dashboard Not Found',
};

const ALLOWED_TYPES = ['global', 'country', 'aoi'];

function getLabel(location, countryData) {
  let country;
  if (location.adm0) {
    country = countryData?.countries.find((c) => c.value === location.adm0)
      ?.label;
  }

  if (location.adm2) {
    const adm2Label = countryData?.subRegions.find(
      (c) => c.value === location.adm2
    )?.label;
    return `${adm2Label}, ${country}`;
  }
  if (location.adm1) {
    const adm1Label = countryData?.regions.find(
      (c) => c.value === location.adm1
    )?.label;
    return `${adm1Label}, ${country}`;
  }
  if (location.adm0) {
    return country;
  }
  return 'global';
}

export const getServerSideProps = async ({ params }) => {
  const [type] = params?.location || [];

  if (type && !ALLOWED_TYPES.includes(type)) {
    return {
      props: notFoundProps,
    };
  }

  let countryData = await getCategorisedCountries(true);

  if (!type || type === 'global') {
    // get global data
    const data = await getSentenceData();
    const parsedSentence = parseSentence(data);
    const description = parseStringWithVars(
      parsedSentence.sentence,
      parsedSentence.params
    );
    return {
      props: {
        title: 'Global Deforestation Rates & Statistics by Country | GFW',
        location: params?.location,
        globalSentence: parsedSentence,
        geodescriber: JSON.stringify(data),
        countryData: JSON.stringify(countryData),
        description,
      },
    };
  }

  try {
    const locationData = await getLocationData(params?.location);
    const { locationName } = locationData || {};

    if (!locationName) {
      return {
        props: notFoundProps,
      };
    }

    const title = `${locationName} Deforestation Rates & Statistics | GFW`;
    const noIndex = !['country'].includes(type);
    const [locationType, adm0, lvl1, lvl2] = params?.location;
    const adm1 = lvl1 ? parseInt(lvl1, 10) : null;
    const adm2 = lvl2 ? parseInt(lvl2, 10) : null;

    const data = await getSentenceData({
      type: locationType === 'aoi' ? 'country' : locationType,
      adm0,
      adm1,
      adm2,
      threshold: 30,
      extentYear: 2010,
    });

    if (adm0) {
      const regions = await getRegionsProvider({ adm0 });
      const countryLinks = await getCountryLinksSerialized();
      countryData = {
        ...countryData,
        regions: uniqBy(regions.data.rows).map((row) => ({
          id: parseGadm36Id(row.id).adm1,
          value: parseGadm36Id(row.id).adm1,
          label: row.name,
          name: row.name,
        })),
        countryLinks,
      };
    }

    if (adm1) {
      const subRegions = await getSubRegionsProvider(adm0, adm1);
      countryData = {
        ...countryData,
        subRegions: uniqBy(subRegions.data.rows).map((row) => ({
          id: parseGadm36Id(row.id).adm2,
          value: parseGadm36Id(row.id).adm2,
          label: row.name,
          name: row.name,
        })),
      };
    }

    const { locationNames, locationObj } = handleSSRLocationObjects(
      countryData,
      adm0,
      adm1,
      adm2
    );

    const parsedSentence = parseSentence(data, locationNames, locationObj);

    const handleSSRLocation = {
      adm0,
      adm1,
      adm2,
      type: locationType,
      label: getLabel({ adm0, adm1, adm2 }, countryData),
    };

    const description = parseStringWithVars(
      parsedSentence.sentence,
      parsedSentence.params
    );

    return {
      props: {
        title,
        description,
        globalSentence: parsedSentence,
        handleSSRLocation,
        geodescriber: JSON.stringify(data),
        countryData: JSON.stringify(countryData),
        noIndex,
      },
    };
  } catch (err) {
    if (err?.response?.status === 401) {
      return {
        props: {
          error: 401,
          title: 'Area is private | Global Forest Watch',
          errorTitle: 'Area is private',
        },
      };
    }

    return {
      props: notFoundProps,
    };
  }
};

// export const getStaticPaths = async () => {
//   const countryData = await getCountriesProvider();
//   const { rows: countries } = countryData?.data || {};
//   const countryPaths = countries.map((c) => ({
//     params: {
//       location: ['country', c.iso],
//     },
//   }));
//
//   return {
//     paths: ['/dashboards/global/', ...countryPaths] || [],
//     fallback: true,
//   };
// };

const DashboardsPage = (props) => {
  const dispatch = useDispatch();
  const [ready, setReady] = useState(false);
  const { query, asPath, isFallback } = useRouter();
  const fullPathname = asPath?.split('?')?.[0];
  const {
    globalSentence,
    handleSSRLocation,
    geodescriber,
    countryData,
  } = props;

  useEffect(() => {
    const {
      map,
      modalMeta,
      dashboardPrompts,
      category,
      areaOfInterestModal,
      showMap,
      widget,
      ...widgets
    } = decodeQueryParams(query) || {};

    if (map) {
      dispatch(setMapSettings(map));
    }

    if (modalMeta) {
      dispatch(setModalMetaSettings(modalMeta));
    }

    if (dashboardPrompts) {
      dispatch(setDashboardPrompts(dashboardPrompts));
    }

    if (widgets) {
      dispatch(setWidgetsSettings(widgets));
    }

    if (category) {
      dispatch(setWidgetsCategory(category));
    }

    if (showMap) {
      dispatch(setShowMap(showMap));
    }

    if (widget) {
      dispatch(setActiveWidget(widget));
    }

    // SSR Specifics
    if (geodescriber) {
      dispatch(setGeodescriberSSR(JSON.parse(geodescriber)));
    }

    if (countryData) {
      dispatch(setCountriesSSR(JSON.parse(countryData)));
    }
  }, [fullPathname, isFallback]);

  // when setting the query params from the URL we need to make sure we don't render the map
  // on the server otherwise the DOM will be out of sync
  useEffect(() => {
    if (!ready) {
      setReady(true);
    }
  });
  return (
    <PageLayout {...props}>
      <Head>
        <link
          rel="canonical"
          href={`https://www.globalforestwatch.org${fullPathname}`}
        />
      </Head>
      <DashboardsUrlProvider />
      <Dashboards
        ssrLocation={handleSSRLocation}
        globalSentence={globalSentence}
      />
    </PageLayout>
  );
};

DashboardsPage.propTypes = {
  title: PropTypes.string,
  globalSentence: PropTypes.object,
  handleSSRLocation: PropTypes.object,
  geodescriber: PropTypes.string,
  countryData: PropTypes.string,
};

export default DashboardsPage;
<commit_msg>dashboard ssr label if AOI fix<commit_after>import Head from 'next/head';
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import uniqBy from 'lodash/uniqBy';

import useRouter from 'utils/router';
import { decodeQueryParams } from 'utils/url';
import { parseGadm36Id } from 'utils/gadm';
import { parseStringWithVars } from 'utils/strings';

import { getLocationData } from 'services/location';
import {
  // getCountriesProvider,
  getRegionsProvider,
  getSubRegionsProvider,
  getCategorisedCountries,
  getCountryLinksSerialized,
} from 'services/country';

import PageLayout from 'wrappers/page';
import Dashboards from 'layouts/dashboards';

import DashboardsUrlProvider from 'providers/dashboards-url-provider';

import { setCountriesSSR } from 'providers/country-data-provider/actions';

import {
  getSentenceData,
  parseSentence,
  handleSSRLocationObjects,
} from 'services/sentences';

import { setGeodescriberSSR } from 'providers/geodescriber-provider/actions';
import { setMapSettings } from 'components/map/actions';
import { setModalMetaSettings } from 'components/modals/meta/actions';
import { setDashboardPrompts } from 'components/prompts/dashboard-prompts/actions';

import {
  setWidgetsSettings,
  setWidgetsCategory,
  setShowMap,
  setActiveWidget,
} from 'components/widgets/actions';

const notFoundProps = {
  error: 404,
  title: 'Dashboard Not Found | Global Forest Watch',
  errorTitle: 'Dashboard Not Found',
};

const ALLOWED_TYPES = ['global', 'country', 'aoi'];

// @todo : check AOI area label
function getLabel(location, countryData) {
  let country;
  if (location.adm0) {
    country = countryData?.countries.find((c) => c.value === location.adm0)
      ?.label;
  }

  if (location.adm2) {
    const adm2Label = countryData?.subRegions.find(
      (c) => c.value === location.adm2
    )?.label;
    return `${adm2Label}, ${country}`;
  }
  if (location.adm1) {
    const adm1Label = countryData?.regions.find(
      (c) => c.value === location.adm1
    )?.label;
    return `${adm1Label}, ${country}`;
  }
  if (location.adm0) {
    return country;
  }
  return 'global';
}

export const getServerSideProps = async ({ params }) => {
  const [type] = params?.location || [];

  if (type && !ALLOWED_TYPES.includes(type)) {
    return {
      props: notFoundProps,
    };
  }

  let countryData = await getCategorisedCountries(true);

  if (!type || type === 'global') {
    // get global data
    const data = await getSentenceData();
    const parsedSentence = parseSentence(data);
    const description = parseStringWithVars(
      parsedSentence.sentence,
      parsedSentence.params
    );
    return {
      props: {
        title: 'Global Deforestation Rates & Statistics by Country | GFW',
        location: params?.location,
        globalSentence: parsedSentence,
        geodescriber: JSON.stringify(data),
        countryData: JSON.stringify(countryData),
        description,
      },
    };
  }

  try {
    const locationData = await getLocationData(params?.location);
    const { locationName } = locationData || {};

    if (!locationName) {
      return {
        props: notFoundProps,
      };
    }

    const title = `${locationName} Deforestation Rates & Statistics | GFW`;
    const noIndex = !['country'].includes(type);
    const [locationType, adm0, lvl1, lvl2] = params?.location;
    const adm1 = lvl1 ? parseInt(lvl1, 10) : null;
    const adm2 = lvl2 ? parseInt(lvl2, 10) : null;

    const data = await getSentenceData({
      type: locationType === 'aoi' ? 'country' : locationType,
      adm0,
      adm1,
      adm2,
      threshold: 30,
      extentYear: 2010,
    });

    if (adm0) {
      const regions = await getRegionsProvider({ adm0 });
      const countryLinks = await getCountryLinksSerialized();
      countryData = {
        ...countryData,
        regions: uniqBy(regions.data.rows).map((row) => ({
          id: parseGadm36Id(row.id).adm1,
          value: parseGadm36Id(row.id).adm1,
          label: row.name,
          name: row.name,
        })),
        countryLinks,
      };
    }

    if (adm1) {
      const subRegions = await getSubRegionsProvider(adm0, adm1);
      countryData = {
        ...countryData,
        subRegions: uniqBy(subRegions.data.rows).map((row) => ({
          id: parseGadm36Id(row.id).adm2,
          value: parseGadm36Id(row.id).adm2,
          label: row.name,
          name: row.name,
        })),
      };
    }

    const { locationNames, locationObj } = handleSSRLocationObjects(
      countryData,
      adm0,
      adm1,
      adm2
    );

    const parsedSentence = parseSentence(data, locationNames, locationObj);
    const label = getLabel({ adm0, adm1, adm2 }, countryData);

    const handleSSRLocation = {
      adm0,
      adm1,
      adm2,
      type: locationType,
      label: label || null,
    };

    const description = parseStringWithVars(
      parsedSentence.sentence,
      parsedSentence.params
    );

    return {
      props: {
        title,
        description,
        globalSentence: parsedSentence,
        handleSSRLocation,
        geodescriber: JSON.stringify(data),
        countryData: JSON.stringify(countryData),
        noIndex,
      },
    };
  } catch (err) {
    if (err?.response?.status === 401) {
      return {
        props: {
          error: 401,
          title: 'Area is private | Global Forest Watch',
          errorTitle: 'Area is private',
        },
      };
    }

    return {
      props: notFoundProps,
    };
  }
};

// export const getStaticPaths = async () => {
//   const countryData = await getCountriesProvider();
//   const { rows: countries } = countryData?.data || {};
//   const countryPaths = countries.map((c) => ({
//     params: {
//       location: ['country', c.iso],
//     },
//   }));
//
//   return {
//     paths: ['/dashboards/global/', ...countryPaths] || [],
//     fallback: true,
//   };
// };

const DashboardsPage = (props) => {
  const dispatch = useDispatch();
  const [ready, setReady] = useState(false);
  const { query, asPath, isFallback } = useRouter();
  const fullPathname = asPath?.split('?')?.[0];
  const {
    globalSentence,
    handleSSRLocation,
    geodescriber,
    countryData,
  } = props;

  useEffect(() => {
    const {
      map,
      modalMeta,
      dashboardPrompts,
      category,
      areaOfInterestModal,
      showMap,
      widget,
      ...widgets
    } = decodeQueryParams(query) || {};

    if (map) {
      dispatch(setMapSettings(map));
    }

    if (modalMeta) {
      dispatch(setModalMetaSettings(modalMeta));
    }

    if (dashboardPrompts) {
      dispatch(setDashboardPrompts(dashboardPrompts));
    }

    if (widgets) {
      dispatch(setWidgetsSettings(widgets));
    }

    if (category) {
      dispatch(setWidgetsCategory(category));
    }

    if (showMap) {
      dispatch(setShowMap(showMap));
    }

    if (widget) {
      dispatch(setActiveWidget(widget));
    }

    // SSR Specifics
    if (geodescriber) {
      dispatch(setGeodescriberSSR(JSON.parse(geodescriber)));
    }

    if (countryData) {
      dispatch(setCountriesSSR(JSON.parse(countryData)));
    }
  }, [fullPathname, isFallback]);

  // when setting the query params from the URL we need to make sure we don't render the map
  // on the server otherwise the DOM will be out of sync
  useEffect(() => {
    if (!ready) {
      setReady(true);
    }
  });
  return (
    <PageLayout {...props}>
      <Head>
        <link
          rel="canonical"
          href={`https://www.globalforestwatch.org${fullPathname}`}
        />
      </Head>
      <DashboardsUrlProvider />
      <Dashboards
        ssrLocation={handleSSRLocation}
        globalSentence={globalSentence}
      />
    </PageLayout>
  );
};

DashboardsPage.propTypes = {
  title: PropTypes.string,
  globalSentence: PropTypes.object,
  handleSSRLocation: PropTypes.object,
  geodescriber: PropTypes.string,
  countryData: PropTypes.string,
};

export default DashboardsPage;
<|endoftext|>


<commit_before>let path = require('path');
let utils = require('./utils');
let config = require('../config');
let vueLoaderConfig = require('./vue-loader.conf');

module.exports = {
  entry: {
    'app': utils.resolve('src/main.js'),
    'background': utils.resolve('src/chrome/background.js'),
    'content': utils.resolve('src/chrome/content.js'),
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production' ?
      config.build.assetsPublicPath : config.dev.assetsPublicPath,
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': utils.resolve('src'),
      'styles': utils.resolve('src/styles'),
    },
  },
  module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader',
      options: vueLoaderConfig,
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [utils.resolve('src'), utils.resolve('test')],
    },
    /* {
      test: /\.(js|vue)$/,
      loader: 'eslint-loader',
      enforce: 'pre',
      include: [utils.resolve('src'), utils.resolve('test')],
    },*/
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]'),
      },
    },
    {
      test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('media/[name].[hash:7].[ext]'),
      },
    },
    {
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('fonts/[name].[hash:7].[ext]'),
      },
    },
    ],
  },
};
<commit_msg>Remove unused variable<commit_after>let utils = require('./utils');
let config = require('../config');
let vueLoaderConfig = require('./vue-loader.conf');

module.exports = {
  entry: {
    'app': utils.resolve('src/main.js'),
    'background': utils.resolve('src/chrome/background.js'),
    'content': utils.resolve('src/chrome/content.js'),
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production' ?
      config.build.assetsPublicPath : config.dev.assetsPublicPath,
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      '@': utils.resolve('src'),
      'styles': utils.resolve('src/styles'),
    },
  },
  module: {
    rules: [{
      test: /\.vue$/,
      loader: 'vue-loader',
      options: vueLoaderConfig,
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [utils.resolve('src'), utils.resolve('test')],
    },
    /* {
      test: /\.(js|vue)$/,
      loader: 'eslint-loader',
      enforce: 'pre',
      include: [utils.resolve('src'), utils.resolve('test')],
    },*/
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]'),
      },
    },
    {
      test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('media/[name].[hash:7].[ext]'),
      },
    },
    {
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('fonts/[name].[hash:7].[ext]'),
      },
    },
    ],
  },
};
<|endoftext|>