您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Repairs embeds in your own and your friend soup. Fixes embeds everywhere if there is a link in the description
当前为
- // ==UserScript==
- // @name soup.io: EmbedFix
- // @namespace http://xcvbnm.org/
- // @author Nordern
- // @description Repairs embeds in your own and your friend soup. Fixes embeds everywhere if there is a link in the description
- // @version 0.2
- // @match http://*.soup.io/*
- // @match https://*.soup.io/*
- // @exclude http://www.soup.io/frames/*
- // @exclude http://www.soup.io/remote/*
- // @license public domain, MediaEmbed has MIT Licence
- // @run-at document-end
- // ==/UserScript==
- // Available on github under: https://github.com/edave64/souplements/blob/master/youtube-fix/
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
- /**
- * This code snippet allows you to intercept the loading of new elements and modify the loaded posts.
- * The basic idea is to allow filtering out posts before they are inserted into the dom, and thus before their assets
- * are loaded. This reduces stress on both the client and the asset servers.
- *
- * To use the filter, register the event "processBatch" in SOUP.Endless.
- * Example:
- *
- * SOUP.Endless.on("processBatch", function (doc) {
- * // your code here
- * });
- *
- * The doc argument represents a temporary HTMLDocument node, storing the new loaded posts. You can work with it
- * like you can work with ''document''.
- *
- * Be careful to never remove all posts, otherwise Soup will assume you reached the end.
- *
- * Please keep in mind that soup already has some filters build in: http://faq.soup.io/post/4328678
- * These are probably easier on the servers.
- *
- * Licence: Public domain
- *
- * UPDATE 1.1:
- * The soup event-api was used! I just used it wrong. It is supposed to be a template. The event is now fired on
- * SOUP.Endless instead of SOUP.Events
- *
- * UPDATE 1.2:
- * Also trigger for loaded in reactions
- */
- (function () {
- // Add events to SOUP.Endless
- if (!SOUP.Endless.trigger) {
- SOUP.tools.extend(SOUP.Endless, SOUP.Events);
- }
- if (Ajax.Request._EndlessFilter) return;
- var oldRequest = Ajax.Request;
- function getLoadAboveURL() {
- var url = $("endless_top_post").href;
- return url.match(/[&?]newer=1/) ? url : url + (url.indexOf("?") >= 0 ? "&" : "?") + "newer=1";
- }
- function getLoadBelowURL() {
- return SOUP.Endless.next_url.replace(/&?newer=1&?/g, "");
- }
- function catchBatchLoad (path, options) {
- var oldSuccess = options.onSuccess;
- options.onSuccess = function (response) {
- var text = response.responseText,
- pipePosition = text.indexOf("|"),
- nextPath = text.substring(0, pipePosition),
- content = text.substring(pipePosition + 1),
- parser = new DOMParser(),
- xmlDoc = parser.parseFromString(content, "text/html"),
- root = xmlDoc.body;
- root.setAttribute("id", "posts");
- SOUP.Endless.trigger("processBatch", xmlDoc);
- response.responseText = nextPath + "|" + root.innerHTML;
- return oldSuccess.apply(this, arguments);
- };
- return oldRequest.apply(this, arguments);
- }
- function catchPreviewLoad (path, options) {
- var oldSuccess = options.onSuccess;
- options.onSuccess = function (response) {
- var content = response.responseText,
- parser = new DOMParser(),
- xmlDoc = parser.parseFromString(content, "text/html"),
- root = xmlDoc.body;
- root.setAttribute("id", "posts");
- SOUP.Endless.trigger("processBatch", xmlDoc);
- response.responseText = root.innerHTML;
- return oldSuccess.apply(this, arguments);
- };
- return oldRequest.apply(this, arguments);
- }
- Ajax.Request = function (path, options) {
- var aboveURL = getLoadAboveURL();
- var belowURL = getLoadBelowURL();
- if (path === aboveURL || path === belowURL) {
- return catchBatchLoad.apply(this, arguments);
- }
- if (path.startsWith("http://" + document.location.host + "/preview/")) {
- return catchPreviewLoad.apply(this, arguments);
- }
- return oldRequest.apply(this, arguments);
- };
- Ajax.Request._EndlessFilter = true;
- Ajax.Request.Events = oldRequest.Events;
- Ajax.Request.prototype = oldRequest.prototype;
- }());
- },{}],2:[function(require,module,exports){
- require("../endlessFilter");
- const MediaEmbedder = require("media-embedder");
- if (!SOUP.EmbedFix) {
- SOUP.EmbedFix = true;
- function fixAll (doc) {
- var video_posts = [].slice.call(doc.getElementsByClassName("post_video"));
- const firstPost = document.querySelector(".post .content");
- let width = 500;
- if (firstPost) {
- width = parseInt(window.getComputedStyle(firstPost).width);
- }
- const height = (width / 16 * 9)|0;
- for (const video_post of video_posts) {
- const embed = video_post.getElementsByClassName("embed")[0];
- if (embed.children.length === 0) {
- const textarea = video_post.querySelector("[name='post[embedcode_or_url]']");
- // Turns out: Edge doesn't support innerText on DomParser elements. or something
- let mediaData = MediaEmbedder.detect(textarea.childNodes[0] ? textarea.childNodes[0].nodeValue : "");
- if (!mediaData) {
- const description = video_post.getElementsByClassName("body")[0];
- if (description) {
- mediaData = MediaEmbedder.detect(description.innerHTML);
- }
- }
- if (mediaData) {
- mediaData.width = width;
- mediaData.height = height;
- embed.innerHTML = MediaEmbedder.buildIframe(mediaData);
- }
- }
- }
- }
- SOUP.Endless.on("processBatch", function (doc) {
- fixAll(doc);
- });
- fixAll(document);
- }
- },{"../endlessFilter":1,"media-embedder":4}],3:[function(require,module,exports){
- module.exports = {
- parse: function (text) {
- const a = document.createElement("a");
- a.href = text;
- a.query = a.search.substring(1);
- return a;
- }
- };
- },{}],4:[function(require,module,exports){
- (function (global){
- "use strict";
- /**
- * @typedef MediaInfo
- * @name MediaInfo
- * @type {object}
- * @property {string} platform - The name of the media platfrom.
- * @property {string} mediaid - A string uniquely identifying on piece of media on the platform
- * @property {number} [height] - The height of the embeded player
- * @property {number} [width] - The width of the embeded player
- * @property {boolean} [allowFullscreen] - True if the player can enter fullscreen
- * @property {boolean} [loop] - True if the player will start over at the end
- * @property {number} [timestamp] - The number of seconds at the begining that will be skiped
- */
- /**
- * @typedef MediaPlatform
- * @name MediaPlatform
- */
- /**
- * Parses a text can either be a url to a video on a platform, or an html
- * snipplet containing an embedding code for one of these platforms.
- *
- * It attemps to extract as much information as possible from this text.
- *
- * @method MediaPlatform~detect
- * @param {string} test - A URL or an html snipplet containing an embed code
- * @returns {MediaInfo|undefined} Information found in the string, undefined if none where found.
- */
- /**
- * Generates a iframe embed html snipplet from a descriptor
- *
- * @method MediaPlatform~buildIframe
- * @param {MediaInfo} descriptor
- * @returns {string} An html snipplet
- */
- /**
- * Generates a link url from a descriptor
- *
- * @method MediaPlatform~buildLink
- * @param {MediaInfo} descriptor
- * @returns {string} A url
- */
- /** @type {Object.<string, MediaPlatform>} */
- const platforms = {
- youtube: require("./platforms/youtube"),
- dailymotion: require("./platforms/dailymotion"),
- vimeo: require("./platforms/vimeo")
- };
- /** @type {MediaPlatform} */
- global.test = module.exports = {
- detect: function(text) {
- for (const platform in platforms) {
- const ret = platforms[platform].detect(text);
- if (ret) {
- ret.platform = platform;
- return ret;
- }
- }
- },
- buildIframe: function (descriptor) {
- const platform = platforms[descriptor.platform];
- return platform.buildIframe(descriptor);
- },
- buildLink: function (descriptor) {
- const platform = platforms[descriptor.platform];
- return platform.buildLink(descriptor);
- }
- };
- }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
- },{"./platforms/dailymotion":6,"./platforms/vimeo":7,"./platforms/youtube":8}],5:[function(require,module,exports){
- "use strict";
- const querystring = require("querystring");
- const UrlHelper = require("./utils/url_helper");
- const DocHelper = require("./utils/doc_helper");
- /**
- * @callback processor
- * @param {UrlObject} url
- * @param {Object} queryObject
- * @return {MediaInfo}
- */
- /**
- * @callback generator
- * @param {MediaInfo} mediaInfo
- * @param {boolean} embedded
- * @param {string[]} queryParts
- * @returns {string} Url
- */
- /**
- * @param {processor} urlProcessor
- * @param {generator} urlGenerator
- * @returns {MediaPlatform}
- */
- module.exports = function (urlProcessor, urlGenerator) {
- function wrappedProcessor (text) {
- try {
- const urlData = UrlHelper.parse(text);
- const qs = querystring.parse(urlData.query);
- return urlProcessor(urlData, qs);
- } catch (e) {
- console.error(e);
- }
- }
- function wrappedGenerator (data, embed) {
- const queryData = [];
- queryData.when = function (condition, val) { if (condition) this.push(val); };
- let url = urlGenerator(data, embed, queryData);
- if (queryData.length > 0) {
- url += "?" + queryData.join("&");
- }
- return url;
- }
- return {
- detect: (text) => {
- // is entire text a url?
- let entire = wrappedProcessor(text),
- ret;
- if (entire) {
- return entire;
- }
- for (const tag of DocHelper.get_nodes(text, "iframe", "embed", "a")) {
- switch (tag.nodeName.toLowerCase()) {
- case "iframe":
- case "embed":
- ret = DocHelper.processIframe(tag, wrappedProcessor);
- if (ret) {
- return ret;
- }
- break;
- case "a":
- ret = wrappedProcessor(tag.getAttribute("href"));
- if (ret) {
- return ret;
- }
- break;
- }
- }
- },
- buildIframe: (data) => {
- return DocHelper.buildIframe(wrappedGenerator(data, true), data.height, data.width, data.allowFullscreen);
- },
- buildLink: (data) => {
- return wrappedGenerator(data, false);
- }
- };
- };
- },{"./utils/doc_helper":9,"./utils/url_helper":10,"querystring":13}],6:[function(require,module,exports){
- "use strict";
- const urlParse = /^\/(embed\/video|video|swf)\/([0-9a-zA-Z]*)/
- module.exports = require("../platform_base")(
- function (urlData, qs) {
- if (urlData.normalizedHost === "dailymotion.com") {
- const urlMatch = urlData.pathname.match(urlParse);
- if (urlMatch) {
- return {
- mediaid: urlMatch[2],
- height: null,
- width: null,
- allowFullscreen: null,
- loop: null,
- timestamp: qs.start || null,
- autoplay: qs.autoplay === "1" || qs.autoPlay === "1"
- }
- }
- }
- },
- function (data, embed, query) {
- let url = embed ? "https://www.dailymotion.com/embed/video/" : "https://www.dailymotion.com/video/";
- url += data.mediaid.replace(/[^0-9a-zA-Z]/g, ""); // sanitize mediaid
- query.when(data.allowFullscreen === false, "fullscreen=1");
- query.when(data.autoplay , "autoplay=1");
- query.when(data.timestamp , "start=" + parseInt(data.timestamp));
- return url;
- }
- );
- },{"../platform_base":5}],7:[function(require,module,exports){
- "use strict";
- const urlParse = /^\/(video\/)?([0-9]*)$/;
- /**
- * @param {string} videoId
- * @param {object} param
- * @returns {MediaInfo}
- */
- function generate (videoId, param) {
- return {
- mediaid: videoId,
- height: null, width: null, timestamp: null,
- allowFullscreen: null,
- loop: param.loop === "1",
- autoplay: param.autoplay === "1"
- }
- }
- module.exports = require("../platform_base")(
- function (urlData, qs) {
- if (urlData.normalizedHost === "vimeo.com" || urlData.normalizedHost === "player.vimeo.com") {
- if (urlData.pathname === "/moogaloop.swf") {
- return generate(qs.clip_id, qs);
- }
- const urlMatch = urlData.pathname.match(urlParse);
- if (urlMatch) {
- return generate(urlMatch[2], qs);
- }
- }
- },
- function (data, embed, query) {
- let url = embed ? "https://player.vimeo.com/video/" : "https://vimeo.com/";
- url += data.mediaid.replace(/[^0-9]/g, ""); // sanitize mediaid
- query.when(data.loop, "loop=1");
- query.when(data.autoplay, "autoplay=1");
- return url;
- }
- );
- },{"../platform_base":5}],8:[function(require,module,exports){
- "use strict";
- const querystring = require("querystring");
- const embedUrlParse = /^\/(embed|v)\/([0-9a-zA-Z\-_]*)(.*)/;
- /**
- * @param {string} videoId
- * @param {object} param
- * @returns {MediaInfo}
- */
- function generate (videoId, param) {
- return {
- mediaid: videoId,
- height: null, width: null,
- allowFullscreen: param.fs !== "0",
- timestamp: param.t || param.time || param.start || null,
- loop: param.loop === "1",
- autoplay: param.autoplay === "1"
- }
- }
- module.exports = require("../platform_base")(
- function (urlData, qs) {
- if (urlData.normalizedHost === "youtube.com") {
- if (qs.v) {
- return generate(qs.v, qs);
- }
- const embedUrlMatch = urlData.pathname.match(embedUrlParse);
- if (embedUrlMatch) {
- // youtube /v/ urls can be kind of odd and and append the query with & to the path
- const vUrlQs = querystring.parse(embedUrlMatch[3]);
- return generate(embedUrlMatch[2], Object.assign({}, qs, vUrlQs));
- }
- } else if (urlData.normalizedHost === "youtu.be") {
- const qs = querystring.parse(urlData.query);
- return generate(urlData.pathname.slice(1), qs);
- }
- },
- function (data, embed, query) {
- let url = embed ? "https://www.youtube.com/embed/" : "https://www.youtube.com/watch";
- const mediaid = data.mediaid.replace(/[^0-9a-zA-Z\-_]/g, ""); // sanitize mediaid
- query.when(data.allowFullscreen === false, "fs=1");
- query.when(data.loop, "loop=1");
- query.when(data.autoplay, "autoplay=1");
- if (data.timestamp) {
- query.push("start=" + data.timestamp.replace(/[^0-9hms]/g, ""));
- }
- if (embed) {
- url += mediaid;
- } else {
- query.push("v=" + mediaid)
- }
- return url;
- }
- );
- },{"../platform_base":5,"querystring":13}],9:[function(require,module,exports){
- const DOMParser = (window.window).DOMParser;
- module.exports = {
- get_nodes: function (text, ...node_types) {
- let parser = (new DOMParser ()).parseFromString("<html><body>" + text + "</body></html>", "text/html");
- var tags = [];
- for (const node_type of node_types) {
- tags.push.apply(tags, parser.getElementsByTagName(node_type));
- }
- return tags;
- },
- processIframe: function (iframe, urlProcessor) {
- const ret = urlProcessor(iframe.getAttribute("src"));
- if (ret) {
- ret.allowFullscreen = iframe.getAttribute("allowfullscreen") != null;
- ret.height = iframe.getAttribute("height");
- ret.width = iframe.getAttribute("width");
- return ret;
- }
- },
- buildIframe: function (src, height, width, allowFullscreen) {
- let ret = "<iframe "
- if (height != null) {
- ret += 'height="' + parseInt(height) + '" '
- }
- if (width != null) {
- ret += 'width="' + parseInt(width) + '" '
- }
- if (allowFullscreen === true) {
- ret += 'allowfullscreen webkitallowfullscreen mozallowfullscreen '
- }
- ret += 'frameborder="0" src="' + src + '"></iframe>'
- return ret;
- }
- };
- },{}],10:[function(require,module,exports){
- const url = require("url");
- const querystring = require("querystring");
- module.exports = {
- parse: function (text) {
- let fullUrl = url.parse(text);
- if (fullUrl.protocol === null) {
- fullUrl = url.parse("test:" + (text.startsWith("//") ? "" : "//") + text);
- }
- if (fullUrl.host) {
- fullUrl.normalizedHost = fullUrl.host.startsWith("www.") ? fullUrl.host.substring(4) : fullUrl.host;
- }
- return fullUrl;
- }
- };
- },{"querystring":13,"url":3}],11:[function(require,module,exports){
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to permit
- // persons to whom the Software is furnished to do so, subject to the
- // following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
- 'use strict';
- // If obj.hasOwnProperty has been overridden, then calling
- // obj.hasOwnProperty(prop) will break.
- // See: https://github.com/joyent/node/issues/1707
- function hasOwnProperty(obj, prop) {
- return Object.prototype.hasOwnProperty.call(obj, prop);
- }
- module.exports = function(qs, sep, eq, options) {
- sep = sep || '&';
- eq = eq || '=';
- var obj = {};
- if (typeof qs !== 'string' || qs.length === 0) {
- return obj;
- }
- var regexp = /\+/g;
- qs = qs.split(sep);
- var maxKeys = 1000;
- if (options && typeof options.maxKeys === 'number') {
- maxKeys = options.maxKeys;
- }
- var len = qs.length;
- // maxKeys <= 0 means that we should not limit keys count
- if (maxKeys > 0 && len > maxKeys) {
- len = maxKeys;
- }
- for (var i = 0; i < len; ++i) {
- var x = qs[i].replace(regexp, '%20'),
- idx = x.indexOf(eq),
- kstr, vstr, k, v;
- if (idx >= 0) {
- kstr = x.substr(0, idx);
- vstr = x.substr(idx + 1);
- } else {
- kstr = x;
- vstr = '';
- }
- k = decodeURIComponent(kstr);
- v = decodeURIComponent(vstr);
- if (!hasOwnProperty(obj, k)) {
- obj[k] = v;
- } else if (isArray(obj[k])) {
- obj[k].push(v);
- } else {
- obj[k] = [obj[k], v];
- }
- }
- return obj;
- };
- var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
- };
- },{}],12:[function(require,module,exports){
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a
- // copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to permit
- // persons to whom the Software is furnished to do so, subject to the
- // following conditions:
- //
- // The above copyright notice and this permission notice shall be included
- // in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
- 'use strict';
- var stringifyPrimitive = function(v) {
- switch (typeof v) {
- case 'string':
- return v;
- case 'boolean':
- return v ? 'true' : 'false';
- case 'number':
- return isFinite(v) ? v : '';
- default:
- return '';
- }
- };
- module.exports = function(obj, sep, eq, name) {
- sep = sep || '&';
- eq = eq || '=';
- if (obj === null) {
- obj = undefined;
- }
- if (typeof obj === 'object') {
- return map(objectKeys(obj), function(k) {
- var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
- if (isArray(obj[k])) {
- return map(obj[k], function(v) {
- return ks + encodeURIComponent(stringifyPrimitive(v));
- }).join(sep);
- } else {
- return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
- }
- }).join(sep);
- }
- if (!name) return '';
- return encodeURIComponent(stringifyPrimitive(name)) + eq +
- encodeURIComponent(stringifyPrimitive(obj));
- };
- var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
- };
- function map (xs, f) {
- if (xs.map) return xs.map(f);
- var res = [];
- for (var i = 0; i < xs.length; i++) {
- res.push(f(xs[i], i));
- }
- return res;
- }
- var objectKeys = Object.keys || function (obj) {
- var res = [];
- for (var key in obj) {
- if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
- }
- return res;
- };
- },{}],13:[function(require,module,exports){
- 'use strict';
- exports.decode = exports.parse = require('./decode');
- exports.encode = exports.stringify = require('./encode');
- },{"./decode":11,"./encode":12}]},{},[2]);