From 0220a4c5cef45626cd5a7ecc6d46e9afadead85c Mon Sep 17 00:00:00 2001 From: opi Date: Sun, 20 Jul 2014 13:53:34 +0200 Subject: [PATCH] [enh] Add vshare plugin. --- sources/lib/plugins/vshare/README | 25 +++ sources/lib/plugins/vshare/all.css | 20 +++ sources/lib/plugins/vshare/button.png | Bin 0 -> 710 bytes sources/lib/plugins/vshare/lang/en/lang.php | 6 + sources/lib/plugins/vshare/lang/fr/lang.php | 10 ++ sources/lib/plugins/vshare/lang/ko/lang.php | 10 ++ sources/lib/plugins/vshare/lang/nl/lang.php | 10 ++ sources/lib/plugins/vshare/pdf.css | 16 ++ sources/lib/plugins/vshare/plugin.info.txt | 8 + sources/lib/plugins/vshare/script.js | 35 +++++ sources/lib/plugins/vshare/sites.conf | 32 ++++ sources/lib/plugins/vshare/sites.js | 32 ++++ sources/lib/plugins/vshare/syntax.php | 162 ++++++++++++++++++++ sources/lib/plugins/vshare/video.png | Bin 0 -> 6682 bytes 14 files changed, 366 insertions(+) create mode 100644 sources/lib/plugins/vshare/README create mode 100644 sources/lib/plugins/vshare/all.css create mode 100644 sources/lib/plugins/vshare/button.png create mode 100644 sources/lib/plugins/vshare/lang/en/lang.php create mode 100644 sources/lib/plugins/vshare/lang/fr/lang.php create mode 100644 sources/lib/plugins/vshare/lang/ko/lang.php create mode 100644 sources/lib/plugins/vshare/lang/nl/lang.php create mode 100644 sources/lib/plugins/vshare/pdf.css create mode 100644 sources/lib/plugins/vshare/plugin.info.txt create mode 100644 sources/lib/plugins/vshare/script.js create mode 100644 sources/lib/plugins/vshare/sites.conf create mode 100644 sources/lib/plugins/vshare/sites.js create mode 100644 sources/lib/plugins/vshare/syntax.php create mode 100644 sources/lib/plugins/vshare/video.png diff --git a/sources/lib/plugins/vshare/README b/sources/lib/plugins/vshare/README new file mode 100644 index 0000000..8859d5b --- /dev/null +++ b/sources/lib/plugins/vshare/README @@ -0,0 +1,25 @@ +vshare Plugin for DokuWiki + +All documentation for this plugin can be found at +http://www.dokuwiki.org/plugin:vshare + +If you install this plugin manually, make sure it is installed in +lib/plugins/vshare/ - if the folder is called different it +will not work! + +Please refer to http://www.dokuwiki.org/plugins for additional info +on how to install plugins in DokuWiki. + +---- +Copyright (C) Andreas Gohr + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; version 2 of the License + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +See the COPYING file in your DokuWiki folder for details diff --git a/sources/lib/plugins/vshare/all.css b/sources/lib/plugins/vshare/all.css new file mode 100644 index 0000000..380ac82 --- /dev/null +++ b/sources/lib/plugins/vshare/all.css @@ -0,0 +1,20 @@ +iframe.vshare__left, +div.vshare__left { + float: left; + margin-right: 1em; +} + +iframe.vshare__right, +div.vshare__right { + float: right; + margin-left: 1em; +} + +iframe.vshare__center, +div.vshare__center { + text-align: center; + margin-left: auto; + margin-right: auto; + display: block; +} + diff --git a/sources/lib/plugins/vshare/button.png b/sources/lib/plugins/vshare/button.png new file mode 100644 index 0000000000000000000000000000000000000000..d050afa49b9e71999069d13d604407806e91820c GIT binary patch literal 710 zcmV;%0y+JOP)QB4!Q* zVj3FS3|(Dq|JBsAZf@MT_V|Mb_xA%89|huj*t`!AKwtwB5|YnIOUoMX-o5?zuV23} zKYH}=$gf{NFEcVSz2N5N`u*q6A66zNW;SMKMkb&KHEUKe#K$KvY~8w*K}AKG z;o!l84}n@000M{!WWc#|=hj}neEGG4f)c}zAHNtu8eYA6%b=j32sD73;pfj^44Rrc z3@={1W>8bpVEFqNtmhU;FF*jnqp`BG`UH^u|I?@M|G$6#_y6sApZC7fBu`An#}^~1qdMIXk-GJ4D=%yg8(#kz?Q(oe*gZ>0F60j5Fa3b;0FBr z2U7G8tN;d(4M2#2eElCT1`t3<2K8?blp?u$Qu{NVig^C#Zi#l*w} sjMkt3?%cU`1jGjjAVx~FGeCd=0RK80<3*ZVO#lD@07*qoM6N<$f&|h=AOHXW literal 0 HcmV?d00001 diff --git a/sources/lib/plugins/vshare/lang/en/lang.php b/sources/lib/plugins/vshare/lang/en/lang.php new file mode 100644 index 0000000..2b968c6 --- /dev/null +++ b/sources/lib/plugins/vshare/lang/en/lang.php @@ -0,0 +1,6 @@ + + */ + +$lang['js']['button'] = 'Insère une vidéo depuis des sites de partage vidéo'; +$lang['js']['prompt'] = 'Copiez/collez le lien complet de la page contenant la vidéo ici :'; +$lang['js']['notfound'] = "Désolé, cette URL n'a pas été reconnue. Consultez la documentation sur la syntaxe pour insérer une vidéo manuellement."; \ No newline at end of file diff --git a/sources/lib/plugins/vshare/lang/ko/lang.php b/sources/lib/plugins/vshare/lang/ko/lang.php new file mode 100644 index 0000000..58bab3b --- /dev/null +++ b/sources/lib/plugins/vshare/lang/ko/lang.php @@ -0,0 +1,10 @@ + + */ + +$lang['js']['button'] = '동영상 공유 사이트에서 동영상 넣기'; +$lang['js']['prompt'] = '여기에 동영상 페이지의 전체 URL을 붙여넣으세요:'; +$lang['js']['notfound'] = "죄송하지만 이 URL을 인식할 수 없습니다.\n수동으로 올바른 문법을 넣는 방법에 대해서는 설명서를 참고하세요."; diff --git a/sources/lib/plugins/vshare/lang/nl/lang.php b/sources/lib/plugins/vshare/lang/nl/lang.php new file mode 100644 index 0000000..d855df4 --- /dev/null +++ b/sources/lib/plugins/vshare/lang/nl/lang.php @@ -0,0 +1,10 @@ + + */ +$lang['js']['button'] = 'Voeg een video van een video-delen website in'; +$lang['js']['prompt'] = 'Plak hier de volledige URL voor de video pagina:'; +$lang['js']['notfound'] = "Sorry, deze URL werd niet herkend.\nRaadpleeg de documentatie over de juiste syntax om een URL handmatig in te voegen."; diff --git a/sources/lib/plugins/vshare/pdf.css b/sources/lib/plugins/vshare/pdf.css new file mode 100644 index 0000000..6238a90 --- /dev/null +++ b/sources/lib/plugins/vshare/pdf.css @@ -0,0 +1,16 @@ + +div.vshare__left, +div.vshare__right, +div.vshare__center { + border: 1px solid #ccc; + text-align: center; + padding: 2em; +} + +a.vshare { + color: #aaa; + font-size: 2em; + font-weight: bold; + text-decoration: none; +} + diff --git a/sources/lib/plugins/vshare/plugin.info.txt b/sources/lib/plugins/vshare/plugin.info.txt new file mode 100644 index 0000000..e59c961 --- /dev/null +++ b/sources/lib/plugins/vshare/plugin.info.txt @@ -0,0 +1,8 @@ +base vshare +author Andreas Gohr +email andi@splitbrain.org +date 2013-10-22 +name Video Sharing Site Plugin +desc Easily embed videos from various Video Sharing sites. Example: {{youtube>XXXXXX}} +url http://www.dokuwiki.org/plugin:vshare + diff --git a/sources/lib/plugins/vshare/script.js b/sources/lib/plugins/vshare/script.js new file mode 100644 index 0000000..45c7c27 --- /dev/null +++ b/sources/lib/plugins/vshare/script.js @@ -0,0 +1,35 @@ + +/** + * Append a toolbar button + */ +if(window.toolbar != undefined){ + toolbar[toolbar.length] = {"type": "pluginvshare", + "title": LANG['plugins']['vshare']['button'], + "icon": DOKU_BASE+"lib/plugins/vshare/button.png", + "key": ""}; +} + +/** + * Try to determine the video service, extract the ID and insert + * the correct syntax + */ +function tb_pluginvshare(btn, props, edid) { + var text = prompt(LANG['plugins']['vshare']['prompt']); + if(!text) return; + + // This includes the site patterns: + /* DOKUWIKI:include sites.js */ + + for (var key in sites){ + var RE = new RegExp(sites[key],'i'); + var match = text.match(RE); + if(match){ + var code = '{{'+key+'>'+match[1]+'?medium}}'; + insertAtCarret(edid, code); + return; + } + } + + alert(LANG['plugins']['vshare']['notfound']); +} + diff --git a/sources/lib/plugins/vshare/sites.conf b/sources/lib/plugins/vshare/sites.conf new file mode 100644 index 0000000..6da3604 --- /dev/null +++ b/sources/lib/plugins/vshare/sites.conf @@ -0,0 +1,32 @@ +# configure video site flash or iframe URLs here, @VIDEO@ is the ID placeholder + +vimeo iframe http://player.vimeo.com/video/@VIDEO@ +ustream iframe http://www.ustream.tv/embed/recorded/@VIDEO@ +youtube iframe http://www.youtube.com/embed/@VIDEO@ + +12seconds flash http://embed.12seconds.tv/players/remotePlayer.swf?vid=@VIDEO@ +5min flash http://www.5min.com/Embeded/@VIDEO@/ +bambuser flash http://bambuser.com/r/player.swf?vid=@VIDEO@&context=external +bliptv flash http://blip.tv/scripts/flash/showplayer.swf?file=http%3A%2F%2Fblip.tv/rss/flash/@VIDEO@ +blogtv flash http://www.blogtv.com/vb/@VIDEO@ +break flash http://embed.break.com/@VIDEO@ +clipfish flash http://www.clipfish.de/cfng/flash/clipfish_player_3.swf?as=0&vid=@VIDEO@&r=1&angebot=extern& +current flash http://current.com/e/@VIDEO@ +dailymotion flash http://www.dailymotion.com/swf/@VIDEO@ +googlevideo flash http://video.google.com/googleplayer.swf?docid=@VIDEO@ +gtrailers flash http://www.gametrailers.com/remote_wrap.php?mid=@VIDEO@ +justintv flash http://www.justin.tv/widgets/jtv_tip_embed.swf?tip_id=@VIDEO@&channel=justin.tv +metacafe flash http://www.metacafe.com/fplayer/@VIDEO@/foo.swf +myspacetv flash http://lads.myspace.com/videos/vplayer.swf?m=@VIDEO@&v=2&type=video +rcmovie flash http://www.rcmovie.de/embed/@VIDEO@ +revver flash http://flash.revver.com/player/1.0/player.swf?mediaId=@VIDEO@ +scivee flash http://www.scivee.tv/flash/embedPlayer.swf?id=@VIDEO@&type=3 +sevenload flash http://en.sevenload.com/pl/@VIDEO@/500x408/swf +slideshare flash http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=@VIDEO@&allowFullScreen=true&allowScriptAccess=always +stickam flash http://player.stickam.com/flashVarMediaPlayer/@VIDEO@ +veoh flash http://www.veoh.com/videodetails2.swf?player=videodetailsembedded&type=v&permalinkId=@VIDEO@&id=anonymous +viddler flash http://www.viddler.com/player/@VIDEO@/ + + + + diff --git a/sources/lib/plugins/vshare/sites.js b/sources/lib/plugins/vshare/sites.js new file mode 100644 index 0000000..a343914 --- /dev/null +++ b/sources/lib/plugins/vshare/sites.js @@ -0,0 +1,32 @@ +/** + * video URL recognition patterns + * + * The first match group is used as video ID + * + * You need to touch conf/local.php to refresh the cache after changing + * this file + */ + +var sites = { + 'youtube': 'youtube\\.com/.*[&?]v=([a-z0-9_\\-]+)', + 'vimeo': 'vimeo\\.com\\/(\\d+)', + 'ustream': 'ustream\\.tv\\/recorded\\/(\\d+)\\/', + '12seconds': '12seconds\\.com\\/v\\/([a-z0-9_]+)', + '5min': '5min\\.com\\/Video/.*-([0-9]+)([&?]|$)', + 'clipfish': 'clipfishi\\.de\\/.*\\/video\\/([0-9])+\\/', + 'blogtv': 'blogtv\.com\\/Shows\\/\\d+\\/([a-z0-9]+_[a-z0-9]+)([&?]|$)', + 'current': 'current\\.com\\/items\\/(\\d+)', + 'dailymotion': 'dailymotion\\.com\\/video\\/([a-z0-9]+)_', + 'googlevideo': 'video\\.google\\.com\\/videoplay\\?docid=([\\-\\d]+)', + 'gtrailers': 'gametrailers\\.com\\/.*\\/(\\d+)', + 'justintv': 'justin\\.tv\\/clip\\/([a-f0-9]+)', + 'metacafe': 'metacafe\\.com\\/watch\\/(\\d+)\\/', + 'myspacetv': 'vids\\.myspace\\.com\\/.*videoid=(\\d+)', + 'rcmovie': 'rcmovie\\.de\\/video\\/([a-f0-9]+)\\/', + 'revver': 'revver\\.com\\/video\\/(\\d+)\\/', + 'scivee': 'scivee\\.tv\\/node\\/(\\d+)', + 'sevenload': 'sevenload\\.com\\/.*\\/([a-z0-9]+)-[^\\/]*$', + 'stickam': 'stickam\\.com\\/viewMedia.do\\?mId=(\\d+)', + 'veoh': 'veoh\\.com\\/.*watch[^v]*(v[a-z0-9]+)' +}; + diff --git a/sources/lib/plugins/vshare/syntax.php b/sources/lib/plugins/vshare/syntax.php new file mode 100644 index 0000000..038ccd3 --- /dev/null +++ b/sources/lib/plugins/vshare/syntax.php @@ -0,0 +1,162 @@ + + */ + +if(!defined('DOKU_INC')) die(); +require_once(DOKU_PLUGIN.'syntax.php'); + +class syntax_plugin_vshare extends DokuWiki_Syntax_Plugin { + var $sites; + + /** + * Constructor. + * Intitalizes the supported video sites + */ + function syntax_plugin_vshare(){ + $this->sites = confToHash(dirname(__FILE__).'/sites.conf'); + } + + function getType(){ + return 'substition'; + } + + function getPType(){ + return 'block'; + } + + function getSort(){ + return 159; + } + + + /** + * Connect to the parser + */ + function connectTo($mode) { + $pattern = join('|',array_keys($this->sites)); + $this->Lexer->addSpecialPattern('\{\{\s?(?:'.$pattern.')>[^}]*\}\}',$mode,'plugin_vshare'); + } + + /** + * Parse the parameters + */ + function handle($match, $state, $pos, &$handler){ + $command = substr($match,2,-2); + + // title + list($command,$title) = explode('|',$command); + $title = trim($title); + + // alignment + $align = 0; + if(substr($command,0,1) == ' ') $align += 1; + if(substr($command,-1) == ' ') $align += 2; + $command = trim($command); + + // get site and video + list($site,$vid) = explode('>',$command); + if(!$this->sites[$site]) return null; // unknown site + if(!$vid) return null; // no video!? + + // what size? + list($vid,$param) = explode('?',$vid,2); + if(preg_match('/(\d+)x(\d+)/i',$param,$m)){ // custom + $width = $m[1]; + $height = $m[2]; + }elseif(strpos($param,'small') !== false){ // small + $width = 255; + $height = 210; + }elseif(strpos($param,'large') !== false){ // large + $width = 520; + $height = 406; + }else{ // medium + $width = 425; + $height = 350; + } + + list($type, $url) = explode(' ', $this->sites[$site], 2); + $url = trim($url); + $type = trim($type); + $url = str_replace('@VIDEO@',rawurlencode($vid),$url); + $url = str_replace('@WIDTH@',$width,$url); + $url = str_replace('@HEIGHT@',$height,$url); + list(,$vars) = explode('?',$url,2); + $varr = array(); + parse_str($vars,$varr); + + return array( + 'site' => $site, + 'video' => $vid, + 'url' => $url, + 'vars' => $varr, + 'align' => $align, + 'width' => $width, + 'height' => $height, + 'title' => $title, + 'type' => $type + ); + } + + /** + * Render the flash player + */ + function render($mode, &$R, $data){ + if($mode != 'xhtml') return false; + if(is_null($data)) return false; + + if($data['align'] == 0) $align = 'none'; + if($data['align'] == 1) $align = 'right'; + if($data['align'] == 2) $align = 'left'; + if($data['align'] == 3) $align = 'center'; + if($data['title']) $title = ' title="'.hsc($data['title']).'"'; + + if(is_a($R,'renderer_plugin_dw2pdf')){ + // Output for PDF renderer + $R->doc .= '
'; + + $R->doc .= ''; + $R->doc .= ''; + $R->doc .= ''; + + $R->doc .= '
'; + + $R->doc .= ''; + $R->doc .= ($data['title'] ? hsc($data['title']) : 'Video'); + $R->doc .= ''; + + $R->doc .= '
'; + }else{ + // Normal output + if($data['type'] == 'flash') { + // embed flash + $R->doc .= '
'; + $R->doc .= html_flashobject( + $data['url'], + $data['width'], + $data['height'], + $data['vars'], + $data['vars']); + $R->doc .= '
'; + }else{ + // embed iframe + $R->doc .= ''; + } + } + } +} diff --git a/sources/lib/plugins/vshare/video.png b/sources/lib/plugins/vshare/video.png new file mode 100644 index 0000000000000000000000000000000000000000..8bb325e6c88464792858e8d23e6c9ff2e4e0ed82 GIT binary patch literal 6682 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 U8TnuacyR-$C}_x6$eM-!5AD7T7ytkO literal 0 HcmV?d00001