├── .github └── workflows │ └── dokuwiki.yml ├── README ├── _test ├── GeneralTest.php ├── SitesTest.php └── VideoSyntaxTest.php ├── action.php ├── all.css ├── button.png ├── conf ├── default.php └── metadata.php ├── deleted.files ├── helper.php ├── lang ├── ar │ └── lang.php ├── ckb │ └── lang.php ├── cs │ ├── lang.php │ └── settings.php ├── da │ └── lang.php ├── de-informal │ ├── lang.php │ └── settings.php ├── de │ ├── lang.php │ └── settings.php ├── el │ └── lang.php ├── en │ ├── lang.php │ └── settings.php ├── es │ ├── lang.php │ └── settings.php ├── fa │ └── lang.php ├── fr │ ├── lang.php │ └── settings.php ├── it │ └── lang.php ├── ja │ └── lang.php ├── ko │ ├── lang.php │ └── settings.php ├── nl │ ├── lang.php │ └── settings.php ├── no │ └── lang.php ├── pl │ ├── lang.php │ └── settings.php ├── pt-br │ ├── lang.php │ └── settings.php ├── ru │ ├── lang.php │ └── settings.php ├── tr │ └── lang.php ├── uk │ └── lang.php ├── vi │ ├── lang.php │ └── settings.php ├── zh-tw │ ├── lang.php │ └── settings.php └── zh │ ├── lang.php │ └── settings.php ├── pdf.css ├── plugin.info.txt ├── script.js ├── sites.ini ├── syntax ├── debug.php └── video.php ├── video.png └── video.svg /.github/workflows/dokuwiki.yml: -------------------------------------------------------------------------------- 1 | name: DokuWiki Default Tasks 2 | on: 3 | push: 4 | pull_request: 5 | schedule: 6 | - cron: '56 20 16 * *' 7 | 8 | 9 | jobs: 10 | all: 11 | uses: dokuwiki/github-action/.github/workflows/all.yml@main 12 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | vshare Plugin for DokuWiki 2 | 3 | All documentation for this plugin can be found at 4 | http://www.dokuwiki.org/plugin:vshare 5 | 6 | If you install this plugin manually, make sure it is installed in 7 | lib/plugins/vshare/ - if the folder is called different it 8 | will not work! 9 | 10 | Please refer to http://www.dokuwiki.org/plugins for additional info 11 | on how to install plugins in DokuWiki. 12 | 13 | ---- 14 | Copyright (C) Andreas Gohr 15 | 16 | This program is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU General Public License as published by 18 | the Free Software Foundation; version 2 of the License 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | See the COPYING file in your DokuWiki folder for details 26 | -------------------------------------------------------------------------------- /_test/GeneralTest.php: -------------------------------------------------------------------------------- 1 | assertFileExists($file); 23 | 24 | $info = confToHash($file); 25 | 26 | $this->assertArrayHasKey('base', $info); 27 | $this->assertArrayHasKey('author', $info); 28 | $this->assertArrayHasKey('email', $info); 29 | $this->assertArrayHasKey('date', $info); 30 | $this->assertArrayHasKey('name', $info); 31 | $this->assertArrayHasKey('desc', $info); 32 | $this->assertArrayHasKey('url', $info); 33 | 34 | $this->assertEquals('vshare', $info['base']); 35 | $this->assertRegExp('/^https?:\/\//', $info['url']); 36 | $this->assertTrue(mail_isvalid($info['email'])); 37 | $this->assertRegExp('/^\d\d\d\d-\d\d-\d\d$/', $info['date']); 38 | $this->assertTrue(false !== strtotime($info['date'])); 39 | } 40 | 41 | /** 42 | * Test to ensure that every conf['...'] entry in conf/default.php has a corresponding meta['...'] entry in 43 | * conf/metadata.php. 44 | */ 45 | public function testPluginConf(): void 46 | { 47 | $conf_file = __DIR__ . '/../conf/default.php'; 48 | $meta_file = __DIR__ . '/../conf/metadata.php'; 49 | 50 | if (!file_exists($conf_file) && !file_exists($meta_file)) { 51 | self::markTestSkipped('No config files exist -> skipping test'); 52 | } 53 | 54 | if (file_exists($conf_file)) { 55 | include($conf_file); 56 | } 57 | if (file_exists($meta_file)) { 58 | include($meta_file); 59 | } 60 | 61 | $this->assertEquals( 62 | gettype($conf), 63 | gettype($meta), 64 | 'Both ' . DOKU_PLUGIN . 'vshare/conf/default.php and ' . DOKU_PLUGIN . 'vshare/conf/metadata.php have to exist and contain the same keys.' 65 | ); 66 | 67 | if ($conf !== null && $meta !== null) { 68 | foreach ($conf as $key => $value) { 69 | $this->assertArrayHasKey( 70 | $key, 71 | $meta, 72 | 'Key $meta[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'vshare/conf/metadata.php' 73 | ); 74 | } 75 | 76 | foreach ($meta as $key => $value) { 77 | $this->assertArrayHasKey( 78 | $key, 79 | $conf, 80 | 'Key $conf[\'' . $key . '\'] missing in ' . DOKU_PLUGIN . 'vshare/conf/default.php' 81 | ); 82 | } 83 | } 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /_test/SitesTest.php: -------------------------------------------------------------------------------- 1 | $data) { 23 | yield [$site, $data]; 24 | } 25 | } 26 | 27 | /** 28 | * @dataProvider provideSites 29 | * @param string $site 30 | * @param string[] $data 31 | */ 32 | public function testPlaceholder($site, $data) 33 | { 34 | $this->assertArrayHasKey('url', $data, $site); 35 | $this->assertStringContainsString('@VIDEO@', $data['url'], $site); 36 | } 37 | 38 | /** 39 | * @dataProvider provideSites 40 | * @param string $site 41 | * @param string[] $data 42 | */ 43 | public function testRegEx($site, $data) 44 | { 45 | if (empty($data['web']) || empty($data['vid'])) { 46 | $this->markTestSkipped("$site has no sample data configured"); 47 | } 48 | if (empty($data['rex'])) { 49 | $this->markTestSkipped("$site has no regular expression"); 50 | } 51 | 52 | // URL to use 53 | $url = empty($data['emb']) ? $data['web'] : $data['emb']; 54 | 55 | $this->assertSame( 56 | 1, 57 | preg_match('!' . $data['rex'] . '!i', $url, $match), 58 | "$site regex did not match web/emb url" 59 | ); 60 | $this->assertEquals($data['vid'], $match[1], "$site regex did not return vid"); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /_test/VideoSyntaxTest.php: -------------------------------------------------------------------------------- 1 | '']], 29 | ['small&autoplay=false', 255, 143, ['autoplay' => 'false']], 30 | ['178x123&autoplay=false', 178, 123, ['autoplay' => 'false']], 31 | ['autoplay=false', 425, 239, ['autoplay' => 'false']], 32 | ]; 33 | } 34 | 35 | /** 36 | * @dataProvider provideParseSize 37 | * @param string $input 38 | * @param int $ewidth 39 | * @param int $eheight 40 | * @param array $eparams 41 | */ 42 | public function testParseSize($input, $ewidth, $eheight, $eparams = []) 43 | { 44 | $syntax = new \syntax_plugin_vshare_video(); 45 | parse_str($input, $params); 46 | list($width, $height) = $syntax->parseSize($params); 47 | 48 | $this->assertEquals($ewidth, $width, 'width'); 49 | $this->assertEquals($eheight, $height, 'height'); 50 | $this->assertEquals($eparams, $eparams, 'height'); 51 | } 52 | 53 | /** 54 | * @see testHandle 55 | */ 56 | public function provideHandle() 57 | { 58 | return [ 59 | [ 60 | '{{youtube>L-WM8YxwqEU}}', 61 | [ 62 | 'site' => 'youtube', 63 | 'domain' => 'www.youtube-nocookie.com', 64 | 'video' => 'L-WM8YxwqEU', 65 | 'url' => '//www.youtube-nocookie.com/embed/L-WM8YxwqEU?', 66 | 'align' => 'none', 67 | 'width' => 425, 68 | 'height' => 239, 69 | 'title' => '', 70 | ], 71 | ], 72 | [ 73 | '{{youtube>L-WM8YxwqEU?small&start=30&end=45|A random segment of 15 seconds}}', 74 | [ 75 | 'site' => 'youtube', 76 | 'domain' => 'www.youtube-nocookie.com', 77 | 'video' => 'L-WM8YxwqEU', 78 | 'url' => '//www.youtube-nocookie.com/embed/L-WM8YxwqEU?start=30&end=45', 79 | 'align' => 'none', 80 | 'width' => 255, 81 | 'height' => 143, 82 | 'title' => 'A random segment of 15 seconds', 83 | ], 84 | ], 85 | // FIXME add more tests 86 | ]; 87 | } 88 | 89 | /** 90 | * @dataProvider provideHandle 91 | * @param string $input 92 | * @param array $expect 93 | */ 94 | public function testHandle($input, $expect) 95 | { 96 | $syntax = new \syntax_plugin_vshare_video(); 97 | $result = $syntax->handle($input, DOKU_LEXER_MATCHED, 0, new \Doku_Handler()); 98 | $this->assertEquals($expect, $result); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /action.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class action_plugin_vshare extends ActionPlugin 14 | { 15 | /** @inheritDoc */ 16 | public function register(EventHandler $controller) 17 | { 18 | $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'addSites'); 19 | } 20 | 21 | /** 22 | * Add the site regexes 23 | * 24 | * @param Event $event event object by reference 25 | * @param mixed $param optional parameter passed when event was registered 26 | * @return void 27 | */ 28 | public function addSites(Event $event, $param) 29 | { 30 | global $JSINFO; 31 | 32 | $sites = parse_ini_file(__DIR__ . '/sites.ini', true, INI_SCANNER_RAW); 33 | $js = []; 34 | 35 | foreach ($sites as $site => $data) { 36 | if (empty($data['rex'])) continue; 37 | $js[$site] = $data['rex']; 38 | } 39 | 40 | $JSINFO['plugins']['vshare'] = $js; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /all.css: -------------------------------------------------------------------------------- 1 | .vshare { 2 | aspect-ratio: 16/9; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: center; 6 | align-items: center; 7 | text-align: center; 8 | } 9 | 10 | div.vshare { 11 | box-sizing: border-box; 12 | border: 1px solid __border__; 13 | cursor: pointer; 14 | background-image: url(video.svg); 15 | background-position: top left; 16 | background-repeat: no-repeat; 17 | background-size: 5em 5em; 18 | } 19 | 20 | iframe.vshare__left, 21 | div.vshare__left { 22 | float: left; 23 | margin-right: 1em; 24 | } 25 | 26 | iframe.vshare__right, 27 | div.vshare__right { 28 | float: right; 29 | margin-left: 1em; 30 | } 31 | 32 | iframe.vshare__center, 33 | div.vshare__center { 34 | text-align: center; 35 | margin-left: auto; 36 | margin-right: auto; 37 | } 38 | 39 | iframe.vshare__none, 40 | div.vshare__none { 41 | margin: 1px 3px 1px 3px; 42 | } 43 | -------------------------------------------------------------------------------- /button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splitbrain/dokuwiki-plugin-vshare/25789cb50418fada66c0fbc0d9b061e0bbb3100b/button.png -------------------------------------------------------------------------------- /conf/default.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | $conf['gdpr'] = 0; 10 | $conf['extrahard'] = 0; 11 | $conf['debug'] = 0; 12 | -------------------------------------------------------------------------------- /conf/metadata.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | 9 | $meta['gdpr'] = array('onoff'); 10 | $meta['extrahard'] = array('onoff'); 11 | $meta['debug'] = array('onoff'); 12 | -------------------------------------------------------------------------------- /deleted.files: -------------------------------------------------------------------------------- 1 | # This is a list of files that were present in previous releases 2 | # but were removed later. They should not exist in your installation. 3 | _test/SyntaxTest.php 4 | redir.php 5 | sites.conf 6 | sites.js 7 | style.css 8 | syntax.php 9 | test.txt 10 | -------------------------------------------------------------------------------- /helper.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class helper_plugin_vshare extends Plugin 12 | { 13 | /** 14 | * Loads the configures sites and their data 15 | * 16 | * @return array 17 | */ 18 | public static function loadSites() 19 | { 20 | return parse_ini_file(__DIR__ . '/sites.ini', true, INI_SCANNER_RAW); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lang/ar/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'أدرج الفيديو من خلال مواقع تشارك الفيديوهات'; 9 | $lang['js']['prompt'] = 'من فضلك قم بوضع رابط الفيديو كاملا هنا'; 10 | $lang['js']['notfound'] = 'عذرا، الرابط هذا لم يتم قبوله. 11 | نرجو منك العودة إلى الشروحات التي تبين الطريقة المثلى لإدراج الروابط بالشكل الصحيح يدويا.'; 12 | -------------------------------------------------------------------------------- /lang/ckb/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'دانانی ڤیدیۆ لە سایتەکانی هاوبەشی کردنی ڤیدیۆ'; 9 | $lang['js']['prompt'] = 'تکایە URL ەکە بە تەواوی بچەسپێنە بۆ پەڕەی ڤیدیۆکە لێرە:'; 10 | $lang['js']['notfound'] = 'ببوورە، ئەم URLە نەناسراوە. 11 | تکایە ئاماژە بە بەڵگەنامەکان بکە لەسەر چۆنیەتی دانانی ڕستەسازی دروست بە دەستی.'; 12 | -------------------------------------------------------------------------------- /lang/cs/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Petr Kajzar 8 | * @author Jakub Duchek 9 | */ 10 | $lang['js']['button'] = 'Vložit video ze stránek pro sdílení videí'; 11 | $lang['js']['prompt'] = 'Zadejte úplnou adresu URL stránky s videem:'; 12 | $lang['js']['notfound'] = 'Tato adresa URL nebyla rozpoznána. 13 | Podívejte se do dokumentace, jak vložit správnou syntaxi ručně.'; 14 | $lang['js']['click'] = 'Kliknutím načtete toto video. Vaše IP adresa a případně další údaje budou přeneseny do %s.'; 15 | -------------------------------------------------------------------------------- /lang/cs/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Povolit mechanismus click-to-load (klikněte pro načtení)'; 9 | $lang['extrahard'] = 'Povolit rozšířené funkce ochrany soukromí pro vložené soubory, čímž zakážete funkce jako prémiové odběry, sledovat později atd.'; 10 | $lang['debug'] = 'Povolit syntaxi ~~vshare-debug~~ pro vizuální ladění všech nakonfigurovaných webů'; 11 | -------------------------------------------------------------------------------- /lang/da/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Indsæt video fra videodelingssider'; 9 | $lang['js']['prompt'] = 'Indsæt venligst den fulde URL til videoen her:'; 10 | $lang['js']['notfound'] = 'Beklager, denne URL blev ikke genkendt. 11 | Der henvises til dokumentationen for information om den hvordan den korrekte syntaks kan indtastes manuelt.'; 12 | -------------------------------------------------------------------------------- /lang/de-informal/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author F. Mueller-Donath 8 | */ 9 | $lang['js']['button'] = 'Video von Videoplattformen einfügen'; 10 | $lang['js']['prompt'] = 'Bitte füge hier die komplette URL zur Videoseite ein:'; 11 | $lang['js']['notfound'] = 'Die URL wurde leider nicht erkannt. 12 | Bitte lies in der Dokumentation nach wie du die korrekte Syntax für dieses Video manuell eingeben kannst.'; 13 | $lang['js']['click'] = 'Klicke um dieses Video zu laden. Deine IP-Adresse und möglicherweise andere Daten werden an %s übertragen.'; 14 | -------------------------------------------------------------------------------- /lang/de-informal/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = '"Klicken zum Laden" einschalten'; 9 | $lang['debug'] = 'Aktiviere die ~~vshare-debug~~ Syntax um alle konfigurierten Seiten visuell zu debuggen'; 10 | -------------------------------------------------------------------------------- /lang/de/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author F. Mueller-Donath 8 | * @author Andreas Gohr 9 | */ 10 | $lang['js']['button'] = 'Video von Videoplattformen einfügen'; 11 | $lang['js']['prompt'] = 'Bitte fügen Sie hier die komplette URL zur Videoseite ein:'; 12 | $lang['js']['notfound'] = 'Die URL wurde leider nicht erkannt. 13 | Bitte lesen Sie in der Dokumentation nach wie Sie die korrekte Syntax für dieses Video manuell eingeben können.'; 14 | $lang['js']['click'] = 'Klicken Sie, um dieses Video zu laden. Es werden Ihre IP-Adresse und eventuell andere Daten zu %s geschickt.'; 15 | -------------------------------------------------------------------------------- /lang/de/settings.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Joel Strasser 8 | */ 9 | $lang['gdpr'] = 'Click-to-Load-Mechanismus aktivieren'; 10 | $lang['extrahard'] = 'Aktiviere die erweiterten Datenschutzfunktionen für die eingebetteten Videos. Dadurch werden Funktionen wie Premium-Abonnements, „Später ansehen“ und andere deaktiviert.'; 11 | $lang['debug'] = 'Aktivieren Sie die ~~vshare-debug~~-Syntax um alle konfigurierten Seiten visuell zu untersuchen'; 12 | -------------------------------------------------------------------------------- /lang/el/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Εισάγετε βίντεο από τις ιστοσελίδες προβολής βίντεο'; 9 | $lang['js']['prompt'] = 'Παρακαλώ επικολλήστε ολόκληρο το URL στην εικόνα βιντεο εδώ:'; 10 | $lang['js']['notfound'] = 'Συγγνώμη αυτή η σελίδα δεν αναγνωρίστηκε. Παρακαλώ αναφερθείτε στα έγγραφα του πώς να διορθώσετε τη σύνταξη χειροκίνητα.'; 11 | -------------------------------------------------------------------------------- /lang/en/lang.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | $lang['gdpr'] = 'Enable click-to-load mechanism'; 9 | $lang['extrahard'] = 'Enable the enhanced privacy features for the emebds, this will disable features like premium subscriptions, watch later, etc.'; 10 | $lang['debug'] = 'Enable the ~~vshare-debug~~ syntax to visually debug all configured sites'; 11 | 12 | -------------------------------------------------------------------------------- /lang/es/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Domingo Redal 8 | */ 9 | $lang['js']['button'] = 'Insertar vídeo desde un sitio dedicado a compartir vídeos'; 10 | $lang['js']['prompt'] = 'Pegue la dirección URL completa de la página del vídeo aquí:'; 11 | $lang['js']['notfound'] = 'Lo sentimos, la dirección URL no fue reconocida. 12 | Consulte la documentación sobre cómo insertar manualmente la sintaxis correcta.'; 13 | $lang['js']['click'] = 'Click para cargar el video. Si dirección IP y posiblemente algún otro data serán transferidos a %s.'; 14 | -------------------------------------------------------------------------------- /lang/es/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Activar el "click-to-load"'; 9 | -------------------------------------------------------------------------------- /lang/fa/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'ویدئویی از تارنماهای به اشتراک‌گذاری ویدئو وارد نمائید'; 9 | $lang['js']['prompt'] = 'لطفا نشانی اینترنتی کامل صفحه ویدئو را اینجا وارد نمایید'; 10 | $lang['js']['notfound'] = 'با تاسف، این نشانی اینترنتی شناسایی نشد. 11 | لطفا در رابطه با چگونگی وارد کردن نگارش صحیح به صورت دستی به مستندات مراجعه نمائید. '; 12 | -------------------------------------------------------------------------------- /lang/fr/lang.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Fabrice DEJAIGHER 10 | */ 11 | $lang['js']['button'] = 'Insère une vidéo depuis des sites de partage vidéo'; 12 | $lang['js']['prompt'] = 'Copiez/collez le lien complet de la page contenant la vidéo ici :'; 13 | $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.'; 14 | $lang['js']['click'] = 'Cliquez pour charger la vidéo. Votre adresse IP et potentiellement d\'autres informations seront transférées à %s.'; 15 | -------------------------------------------------------------------------------- /lang/fr/settings.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Fabrice Dejaigher 8 | * @author Mabrouk Belhout 9 | */ 10 | $lang['gdpr'] = 'Activer le mécanisme click-to-load'; 11 | $lang['extrahard'] = 'Activez les fonctionnalités de confidentialité avancées pour les intégrations, cela désactivera des options comme les abonnements premium, "Regarder plus tard", etc.'; 12 | $lang['debug'] = 'Activer la syntaxe ~~vshare-debug~~ pour "deboguer" tous les sites configurés.'; 13 | -------------------------------------------------------------------------------- /lang/it/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Inserisci il video dal sito di video sharing'; 9 | $lang['js']['prompt'] = 'Per favore, incolla qui la URL completa della pagina del video:'; 10 | $lang['js']['notfound'] = 'Spiacenti, questa URL non è stata riconosciuta. 11 | Per favore, controlla la documentazione su come inserire a mano la sintassi corretta.'; 12 | -------------------------------------------------------------------------------- /lang/ja/lang.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Myeongjin 10 | */ 11 | $lang['js']['button'] = '동영상 공유 사이트에서 동영상 넣기'; 12 | $lang['js']['prompt'] = '여기에 동영상 페이지의 전체 URL을 붙여넣으세요:'; 13 | $lang['js']['notfound'] = '죄송하지만 이 URL을 인식할 수 없습니다. 14 | 수동으로 올바른 문법을 넣는 방법에 대해서는 설명문서를 참조하세요.'; 15 | -------------------------------------------------------------------------------- /lang/ko/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = '클릭하여 불러오기 기능 활성화'; 9 | -------------------------------------------------------------------------------- /lang/nl/lang.php: -------------------------------------------------------------------------------- 1 | 9 | * @author Mark C. Prins 10 | */ 11 | $lang['js']['button'] = 'Voeg een video van een video-delen website in'; 12 | $lang['js']['prompt'] = 'Plak hier de volledige URL voor de video pagina:'; 13 | $lang['js']['notfound'] = 'Sorry, deze URL werd niet herkend. 14 | Raadpleeg de documentatie over de juiste syntax om een URL handmatig in te voegen.'; 15 | $lang['js']['click'] = 'Klik om de video te laden. Je IP-adres en mogelijk andere data zal gedeeld worden met %s.'; 16 | -------------------------------------------------------------------------------- /lang/nl/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Klik-om-te-laden mechanisme aanzetten'; 9 | $lang['debug'] = 'Schakel de ~~vshare-debug~~ syntax in om visueel alle geconfigureerde site in één keer te controleren op fouten.'; 10 | -------------------------------------------------------------------------------- /lang/no/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Sett inn video fra videodelingstjenester'; 9 | $lang['js']['prompt'] = 'Lim inn hele web-lenken til videodelingssiden her:'; 10 | $lang['js']['notfound'] = 'Beklager, denne lenken ble ikke gjenkjent. 11 | Vær vennlig å sjekk dokumentasjonen for hvordan å sette inn lenke med riktig syntaks.'; 12 | -------------------------------------------------------------------------------- /lang/pl/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Bartek S 8 | */ 9 | $lang['js']['button'] = 'Wstaw wideo z witryn udostępniających wideo'; 10 | $lang['js']['prompt'] = 'Wklej tutaj pełny adres URL strony wideo:'; 11 | $lang['js']['notfound'] = 'Przepraszamy, ten adres URL nie został rozpoznany. 12 | Zapoznaj się z dokumentacją, jak ręcznie wstawiać poprawną składnię.'; 13 | $lang['js']['click'] = 'Kliknij, aby wczytać to wideo. Twój adres IP i ewentualnie inne dane zostaną przekazane do %s.'; 14 | -------------------------------------------------------------------------------- /lang/pl/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Włącz mechanizm „kliknij, aby wczytać”'; 9 | $lang['extrahard'] = 'Włącz rozszerzone funkcje prywatności dla osadzonych materiałów. Spowoduje to wyłączenie takich funkcji, jak subskrypcje premium, opcja „Obejrzyj później” itp.'; 10 | $lang['debug'] = 'Włącz składnię ~~vshare-debug~~, aby wizualnie debugować wszystkie skonfigurowane witryny'; 11 | -------------------------------------------------------------------------------- /lang/pt-br/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Thiago Lima 8 | */ 9 | $lang['js']['button'] = 'Insira o vídeo a partir de um site de compartilhamento de vídeos'; 10 | $lang['js']['prompt'] = 'Por favor, cole aqui a URL completa da página do vídeo:'; 11 | $lang['js']['notfound'] = 'Desculpe, a URL não foi reconhecida. 12 | Por favor, consulte a documentação sobre como inserir a sintaxe correta manualmente.'; 13 | $lang['js']['click'] = 'Clique para carregar este vídeo. Seu endereço IP e possivelmente outros dados serão transferidos para %s.'; 14 | -------------------------------------------------------------------------------- /lang/pt-br/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Ativar mecanismo de clique para carregar'; 9 | $lang['debug'] = 'Habilita a sintaxe ~~vshare-debug~~ para depurar visualmente todos os sites configurados'; 10 | -------------------------------------------------------------------------------- /lang/ru/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Iliya 8 | * @author Yuriy Skalko 9 | */ 10 | $lang['js']['button'] = 'Вставить видео с сайтов обмена видео '; 11 | $lang['js']['prompt'] = 'Пожалуйста, вставьте полный URL на страницу с видео'; 12 | $lang['js']['notfound'] = 'Извините, адрес не распознаётся. Пожалуйста, обратитесь к документации, как вставить правильный синтаксис вручную.'; 13 | $lang['js']['click'] = 'Нажмите для загрузки видео. Ваш IP-адрес и, возможно, другие данные будут переданы на %s.'; 14 | -------------------------------------------------------------------------------- /lang/ru/settings.php: -------------------------------------------------------------------------------- 1 | 7 | * @author Iliya 8 | */ 9 | $lang['gdpr'] = 'Включить механизм загрузки по клику'; 10 | $lang['debug'] = 'Включить макрос ~~vshare-debug~~ для визуальной отладки всех сайтов, указанных в конфигурации'; 11 | -------------------------------------------------------------------------------- /lang/tr/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Video paylaşım sitelerinden video ekle'; 9 | $lang['js']['prompt'] = 'Lütfen tam URL\'yi video sayfasına yapıştırın:'; 10 | $lang['js']['notfound'] = 'Üzgünüz, bu URL tanınmadı. 11 | Lütfen doğru sözdizimini manuel olarak nasıl ekleyeceğinize bakın.'; 12 | -------------------------------------------------------------------------------- /lang/uk/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['prompt'] = 'Вставте повну URL-адресу сторінки відео тут:'; 9 | $lang['js']['notfound'] = 'Вибачте, цю URL-адресу не було розпізнано. Зверніться до документації, щоб дізнатися, як вручну вставити правильний синтаксис.'; 10 | $lang['js']['click'] = 'Натисніть, щоб завантажити це відео. Ваша IP-адреса та, можливо, інші дані будуть передані до %s.'; 11 | -------------------------------------------------------------------------------- /lang/vi/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['button'] = 'Chèn video từ các trang chia sẻ video'; 9 | $lang['js']['prompt'] = 'Vui lòng dán URL đầy đủ vào trang video ở đây:'; 10 | $lang['js']['notfound'] = 'Xin lỗi, URL này không được công nhận. 11 | Vui lòng tham khảo tài liệu về cách chèn đúng cú pháp.'; 12 | $lang['js']['click'] = 'Nhấn để tải video này. Địa chỉ IP của bạn và có thể cả dữ liệu khác sẽ được chuyển đến %s.'; 13 | -------------------------------------------------------------------------------- /lang/vi/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = 'Bật cơ chế nhấp để tải'; 9 | $lang['debug'] = 'Bật cú pháp ~~vshare-debug~~ để gỡ lỗi trực quan tất cả các trang web đã định cấu hình'; 10 | -------------------------------------------------------------------------------- /lang/zh-tw/lang.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['js']['click'] = '點擊以載入此影片。您的IP位址和其他資料(可能)將被傳輸至%s。'; 9 | -------------------------------------------------------------------------------- /lang/zh-tw/settings.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $lang['gdpr'] = '啟用點擊載入機制'; 9 | $lang['debug'] = '啟用~~vshare-debug~~語法以視覺化調試所有已配置的站點'; 10 | -------------------------------------------------------------------------------- /lang/zh/lang.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 黄璟然 8 | * @author Blog.bhyoo.xyz 9 | */ 10 | $lang['js']['button'] = '从视频分享网站插入视频'; 11 | $lang['js']['prompt'] = '请在这里粘贴视频页面的完整链接:'; 12 | $lang['js']['notfound'] = '抱歉,这个网址无法识别。 13 | 请参阅有关如何手动插入正确语法的文档。'; 14 | $lang['js']['click'] = '点击加载此视频。您的IP地址和其他数据(可能)将被传输至%s。'; 15 | -------------------------------------------------------------------------------- /lang/zh/settings.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 铁桶 <2335652849@qq.com> 8 | * @author 黄璟然 9 | */ 10 | $lang['gdpr'] = '启用点击加载机制'; 11 | $lang['extrahard'] = '启用嵌入的增强隐私功能,这将禁用诸如高级订阅、稍后观看等功能'; 12 | $lang['debug'] = '启用~~vshare-debug~~语法以可视化调试所有已配置的站点'; 13 | -------------------------------------------------------------------------------- /pdf.css: -------------------------------------------------------------------------------- 1 | 2 | div.vshare__left, 3 | div.vshare__right, 4 | div.vshare__center { 5 | border: 1px solid #ccc; 6 | text-align: center; 7 | padding: 2em; 8 | } 9 | 10 | a.vshare { 11 | color: #aaa; 12 | font-size: 2em; 13 | font-weight: bold; 14 | text-decoration: none; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /plugin.info.txt: -------------------------------------------------------------------------------- 1 | base vshare 2 | author Andreas Gohr 3 | email andi@splitbrain.org 4 | date 2025-02-21 5 | name Video Sharing Site Plugin 6 | desc Easily embed videos from various Video Sharing sites. Example: {{youtube>XXXXXX}} 7 | url https://www.dokuwiki.org/plugin:vshare 8 | 9 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Append a toolbar button 3 | */ 4 | if (window.toolbar !== undefined) { 5 | toolbar[toolbar.length] = { 6 | "type": "pluginvshare", 7 | "title": LANG['plugins']['vshare']['button'], 8 | "icon": "../../plugins/vshare/button.png", 9 | "key": "" 10 | }; 11 | } 12 | 13 | /** 14 | * Try to determine the video service, extract the ID and insert 15 | * the correct syntax 16 | */ 17 | function tb_pluginvshare(btn, props, edid) { 18 | PluginVShare.edid = edid; 19 | PluginVShare.buildSyntax(); 20 | } 21 | 22 | const PluginVShare = { 23 | edid: null, 24 | 25 | /** 26 | * Ask for URL, extract data and create syntax 27 | */ 28 | buildSyntax: function () { 29 | 30 | const text = prompt(LANG['plugins']['vshare']['prompt']); 31 | if (!text) return; 32 | 33 | for (const [site, rex] of Object.entries(JSINFO.plugins.vshare)) { 34 | const RE = new RegExp(rex, 'i'); 35 | const match = text.match(RE); 36 | if (match) { 37 | const urlparam = ''; 38 | const videoid = match[1]; 39 | PluginVShare.insert(site, videoid, urlparam); 40 | return; 41 | } 42 | } 43 | 44 | alert(LANG['plugins']['vshare']['notfound']); 45 | }, 46 | 47 | /** 48 | * Insert the syntax in the editor 49 | * 50 | * @param {string} key 51 | * @param {string} videoid 52 | * @param {string} urlparam 53 | */ 54 | insert: function (key, videoid, urlparam) { 55 | const code = '{{' + key + '>' + videoid + '?' + urlparam + '}}'; 56 | insertAtCarret(PluginVShare.edid, code); 57 | }, 58 | 59 | /** 60 | * Allow loading videos on click 61 | */ 62 | attachGDPRHandler: function () { 63 | const $videos = jQuery('div.vshare'); 64 | 65 | // add click handler 66 | $videos.on('click', function () { 67 | // create an iframe and copy over the attributes 68 | const iframe = document.createElement('iframe'); 69 | let attr; 70 | let attributes = Array.prototype.slice.call(this.attributes); 71 | while(attr = attributes.pop()) { 72 | iframe.setAttribute(attr.nodeName, attr.nodeValue); 73 | } 74 | // replace the div with the iframe 75 | this.replaceWith(iframe); 76 | }); 77 | 78 | // add info text 79 | $videos.each(function (){ 80 | const $self = jQuery(this); 81 | const info = document.createElement('p'); 82 | info.innerText = LANG.plugins.vshare.click.replace('%s', $self.data('domain')); 83 | $self.append(info); 84 | }); 85 | } 86 | }; 87 | 88 | jQuery(function () { 89 | PluginVShare.attachGDPRHandler(); 90 | }); 91 | -------------------------------------------------------------------------------- /sites.ini: -------------------------------------------------------------------------------- 1 | ; [site] 2 | ; url = the URL that will be loaded into an iframe, should contain at least @VIDEO@ placeholder 3 | ; vid = a public sample video ID 4 | ; web = the full URL to the website for the video identified by vid 5 | ; emb = optional special URL to use for extracting the vid 6 | ; rex = a regular expression that can extract the vid from the web or emb url 7 | ; nfo = a hint on how to find the right URL to paste 8 | 9 | [youtube] 10 | url = //www.youtube-nocookie.com/embed/@VIDEO@ 11 | vid = W86cTIoMv2U 12 | web = https://www.youtube.com/watch?v=W86cTIoMv2U 13 | rex = youtube\.com/.*[&?]v=([a-z0-9_\-]+) 14 | 15 | [vimeo] 16 | url = //player.vimeo.com/video/@VIDEO@ 17 | vid = 916779781 18 | web = https://vimeo.com/916779781 19 | rex = vimeo\.com\/(\d+) 20 | 21 | [slideshare] 22 | url = //www.slideshare.net/slideshow/embed_code/@VIDEO@ 23 | vid = 45544603 24 | web = https://www.slideshare.net/iruska_38/little-cat-45544603 25 | emb = [slideshare id=45544603&doc=littlecat-150307015432-conversion-gate01] 26 | rex = slideshare.*id=(\d+) 27 | nfo = Use the WordPress shortcode 28 | 29 | [dailymotion] 30 | url = //www.dailymotion.com/embed/video/@VIDEO@ 31 | vid = x87k84d 32 | web = https://www.dailymotion.com/video/x87k84d 33 | rex = dailymotion\.com/video/([a-z0-9]+) 34 | 35 | [twitchtv] 36 | url = //player.twitch.tv/?video=@VIDEO@&parent=@DOMAIN@ 37 | vid = 2074388726 38 | web = https://www.twitch.tv/videos/2074388726 39 | 40 | [archiveorg] 41 | url = //archive.org/embed/@VIDEO@ 42 | vid = twitter-1414913663471812612 43 | web = https://archive.org/details/twitter-1414913663471812612 44 | rex = archive\.org/(?:embed|details)/([a-zA-Z0-9_\-]+) 45 | 46 | [soundcloud] 47 | url = https://w.soundcloud.com/player/?url=https%3A//soundcloud.com/@VIDEO@ 48 | vid = marcutio/welcome-to-jamrockmarcutio-remix 49 | web = https://soundcloud.com/marcutio/welcome-to-jamrockmarcutio-remix 50 | rex = soundcloud\.com/([\w-]+/[\w-]+) 51 | 52 | [niconico] 53 | url = //embed.nicovideo.jp/watch/@VIDEO@ 54 | vid = sm11509720 55 | web = https://www.nicovideo.jp/watch/sm11509720 56 | rex = nicovideo\.jp/watch/(sm[0-9]+) 57 | 58 | [bitchute] 59 | url = //www.bitchute.com/embed/@VIDEO@ 60 | vid = hBCtmAgzlgzT 61 | web = https://www.bitchute.com/video/hBCtmAgzlgzT/ 62 | rex = bitchute\.com\/video\/([a-zA-Z0-9_\-]+) 63 | 64 | [coub] 65 | url = //coub.com/embed/@VIDEO@ 66 | vid = 2zije4 67 | web = https://coub.com/view/2zije4 68 | rex = coub\.com\/view\/([a-zA-Z0-9_\-]+) 69 | 70 | [odysee] 71 | url = //odysee.com/$/embed/@VIDEO@ 72 | vid = Catflappattycake/cc19d4ea5edc7ed09a5a883178c8f0317626b0fb 73 | web = https://odysee.com/@BedfordtheBengal:f/Catflappattycake:c 74 | emb = https://odysee.com/$/download/Catflappattycake/cc19d4ea5edc7ed09a5a883178c8f0317626b0fb 75 | rex = odysee\.com/\$/(?:embed|download)/([-%_?=/a-zA-Z0-9]+) 76 | nfo = Use the embed or download URL 77 | 78 | [youku] 79 | url = //player.youku.com/embed/@VIDEO@ 80 | vid = 81 | web = 82 | rex = v\.youku\.com/v_show/id_([0-9A-Za-z=]+)\.html 83 | 84 | [bilibili] 85 | url = //player.bilibili.com/player.html?bvid=@VIDEO@&page=1&as_wide=1&high_quality=1&danmaku=0 86 | vid = BV1aR4y1j78Q 87 | web = https://www.bilibili.com/video/BV1aR4y1j78Q 88 | rex = bilibili\.com\/video\/(BV[0-9A-Za-z]+) 89 | 90 | [msoffice] 91 | url = //hub.video.msn.com/embed/@VIDEO@/ 92 | vid = 93 | web = 94 | rex = (?:office\.com.*[&?]videoid=([a-z0-9\-]+)) 95 | 96 | [msstream] 97 | url = //web.microsoftstream.com/embed/video/@VIDEO@?autoplay=false&showinfo=true 98 | vid = 99 | web = 100 | rex = microsoftstream\.com\/video\/([a-f0-9\-]{36}) 101 | 102 | [rutube] 103 | url = https://rutube.ru/play/embed/@VIDEO@ 104 | vid = 2f578e18146d5483a85cfacf0714f33d 105 | web = https://rutube.ru/video/2f578e18146d5483a85cfacf0714f33d/?r=wd 106 | rex = rutube\.ru\/video\/([a-z0-9]+)\/ 107 | 108 | [gdrive] 109 | url = https://drive.google.com/file/d/@VIDEO@/preview 110 | vid = 12jGYzsKKCl1JEsFA_daw-dpG7Mv_1Rdb 111 | web = https://drive.google.com/file/d/12jGYzsKKCl1JEsFA_daw-dpG7Mv_1Rdb/view?usp=drive_link 112 | rex = drive\.google\.com\/file\/d\/([a-zA-Z0-9_-]+)/ 113 | -------------------------------------------------------------------------------- /syntax/debug.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class syntax_plugin_vshare_debug extends SyntaxPlugin 12 | { 13 | /** @inheritDoc */ 14 | public function getType() 15 | { 16 | return 'substition'; 17 | } 18 | 19 | /** @inheritDoc */ 20 | public function getPType() 21 | { 22 | return 'block'; 23 | } 24 | 25 | /** @inheritDoc */ 26 | public function getSort() 27 | { 28 | return 155; 29 | } 30 | 31 | /** @inheritDoc */ 32 | public function connectTo($mode) 33 | { 34 | if ($this->getConf('debug')) { 35 | $this->Lexer->addSpecialPattern('~~vshare-debug~~', $mode, 'plugin_vshare_debug'); 36 | } 37 | } 38 | 39 | /** @inheritDoc */ 40 | public function handle($match, $state, $pos, Doku_Handler $handler) 41 | { 42 | return []; 43 | } 44 | 45 | /** @inheritDoc */ 46 | public function render($mode, Doku_Renderer $renderer, $handlerdata) 47 | { 48 | if ($mode !== 'xhtml') { 49 | return false; 50 | } 51 | 52 | $sites = helper_plugin_vshare::loadSites(); 53 | $syntax = new syntax_plugin_vshare_video(); 54 | $handler = new \Doku_Handler(); 55 | 56 | 57 | $renderer->header('vshare sites', 1, 0); 58 | 59 | foreach ($sites as $site => $info) { 60 | $renderer->header($site, 2, 0); 61 | 62 | if (!empty($info['vid'])) { 63 | $data = $syntax->handle("{{ $site>{$info['vid']} }}", DOKU_LEXER_MATCHED, 0, $handler); 64 | $syntax->render($mode, $renderer, $data); 65 | } else { 66 | $renderer->p_open(); 67 | $renderer->smiley('FIXME'); 68 | $renderer->cdata(' No sample video ID available'); 69 | $renderer->p_close(); 70 | } 71 | 72 | if (!empty($info['web'])) { 73 | $renderer->p_open(); 74 | $renderer->externallink($info['web']); 75 | $renderer->p_close(); 76 | } else { 77 | $renderer->p_open(); 78 | $renderer->smiley('FIXME'); 79 | $renderer->cdata(' No sample video available'); 80 | $renderer->p_close(); 81 | } 82 | } 83 | 84 | return true; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /syntax/video.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class syntax_plugin_vshare_video extends SyntaxPlugin 12 | { 13 | protected $sites; 14 | 15 | protected $sizes = [ 16 | 'small' => [255, 143], 17 | 'medium' => [425, 239], 18 | 'large' => [520, 293], 19 | 'full' => ['100%', ''], 20 | 'half' => ['50%', ''], 21 | ]; 22 | 23 | protected $alignments = [ 24 | 0 => 'none', 25 | 1 => 'right', 26 | 2 => 'left', 27 | 3 => 'center', 28 | ]; 29 | 30 | /** 31 | * Constructor. 32 | * Intitalizes the supported video sites 33 | */ 34 | public function __construct() 35 | { 36 | $this->sites = helper_plugin_vshare::loadSites(); 37 | } 38 | 39 | /** @inheritdoc */ 40 | public function getType() 41 | { 42 | return 'substition'; 43 | } 44 | 45 | /** @inheritdoc */ 46 | public function getPType() 47 | { 48 | return 'block'; 49 | } 50 | 51 | /** @inheritdoc */ 52 | public function getSort() 53 | { 54 | return 159; 55 | } 56 | 57 | /** @inheritdoc */ 58 | public function connectTo($mode) 59 | { 60 | $pattern = implode('|', array_keys($this->sites)); 61 | $this->Lexer->addSpecialPattern('\{\{\s?(?:' . $pattern . ')>[^}]*\}\}', $mode, 'plugin_vshare_video'); 62 | } 63 | 64 | /** @inheritdoc */ 65 | public function handle($match, $state, $pos, Doku_Handler $handler) 66 | { 67 | $command = substr($match, 2, -2); 68 | 69 | // title 70 | [$command, $title] = sexplode('|', $command, 2, ''); 71 | $title = trim($title); 72 | 73 | // alignment 74 | $align = 0; 75 | if (substr($command, 0, 1) == ' ') ++$align; 76 | if (substr($command, -1) == ' ') $align += 2; 77 | $command = trim($command); 78 | 79 | // get site and video 80 | [$site, $vid] = explode('>', $command); 81 | if (!$this->sites[$site]) return null; // unknown site 82 | if (!$vid) return null; // no video!? 83 | 84 | // what size? 85 | [$vid, $pstr] = sexplode('?', $vid, 2, ''); 86 | parse_str($pstr, $userparams); 87 | [$width, $height] = $this->parseSize($userparams); 88 | 89 | // get URL 90 | $url = $this->insertPlaceholders($this->sites[$site]['url'], $vid, $width, $height); 91 | [$url, $urlpstr] = sexplode('?', $url, 2, ''); 92 | parse_str($urlpstr, $urlparams); 93 | 94 | // merge parameters 95 | $params = array_merge($urlparams, $userparams); 96 | $url = $url . '?' . buildURLparams($params, '&'); 97 | 98 | return [ 99 | 'site' => $site, 100 | 'domain' => parse_url($url, PHP_URL_HOST), 101 | 'video' => $vid, 102 | 'url' => $url, 103 | 'align' => $this->alignments[$align], 104 | 'width' => $width, 105 | 'height' => $height, 106 | 'title' => $title 107 | ]; 108 | } 109 | 110 | /** @inheritdoc */ 111 | public function render($mode, Doku_Renderer $R, $data) 112 | { 113 | if ($mode != 'xhtml') return false; 114 | if (is_null($data)) return false; 115 | 116 | if (is_a($R, 'renderer_plugin_dw2pdf')) { 117 | $R->doc .= $this->pdf($data); 118 | } else { 119 | $R->doc .= $this->iframe($data, $this->getConf('gdpr') ? 'div' : 'iframe'); 120 | } 121 | return true; 122 | } 123 | 124 | /** 125 | * Prepare the HTML for output of the embed iframe 126 | * @param array $data 127 | * @param string $element Can be used to not directly embed the iframe 128 | * @return string 129 | */ 130 | public function iframe($data, $element = 'iframe') 131 | { 132 | $attributes = [ 133 | 'src' => $data['url'], 134 | 'width' => $data['width'], 135 | 'height' => $data['height'], 136 | 'style' => $this->sizeToStyle($data['width'], $data['height']), 137 | 'class' => 'vshare vshare__' . $data['align'], 138 | 'allowfullscreen' => '', 139 | 'frameborder' => 0, 140 | 'scrolling' => 'no', 141 | 'data-domain' => $data['domain'], 142 | 'loading' => 'lazy', 143 | ]; 144 | if ($this->getConf('extrahard')) { 145 | $attributes = array_merge($attributes, $this->hardenedIframeAttributes()); 146 | } 147 | 148 | return "<$element " 149 | . buildAttributes($attributes) 150 | . '>

' . hsc($data['title']) . "

"; 151 | } 152 | 153 | /** 154 | * Create a style attribute for the given size 155 | * 156 | * @param int|string $width 157 | * @param int|string $height 158 | * @return string 159 | */ 160 | public function sizeToStyle($width, $height) 161 | { 162 | // no unit? use px 163 | if ($width && $width == (int)$width) { 164 | $width .= 'px'; 165 | } 166 | // no unit? use px 167 | if ($height && $height == (int)$height) { 168 | $height .= 'px'; 169 | } 170 | 171 | $style = ''; 172 | if ($width) $style .= 'width:' . $width . ';'; 173 | if ($height) $style .= 'height:' . $height . ';'; 174 | return $style; 175 | } 176 | 177 | /** 178 | * Prepare the HTML for output in PDF exports 179 | * 180 | * @param array $data 181 | * @return string 182 | */ 183 | public function pdf($data) 184 | { 185 | $html = '
'; 188 | 189 | $html .= ''; 190 | $html .= ''; 191 | $html .= ''; 192 | 193 | $html .= '
'; 194 | 195 | $html .= ''; 196 | $html .= ($data['title'] ? hsc($data['title']) : 'Video'); 197 | $html .= ''; 198 | 199 | $html .= '
'; 200 | 201 | return $html; 202 | } 203 | 204 | /** 205 | * Fill the placeholders in the given URL 206 | * 207 | * @param string $url 208 | * @param string $vid 209 | * @param int|string $width 210 | * @param int|string $height 211 | * @return string 212 | */ 213 | public function insertPlaceholders($url, $vid, $width, $height) 214 | { 215 | global $INPUT; 216 | $url = str_replace('@VIDEO@', rawurlencode($vid), $url); 217 | $url = str_replace('@DOMAIN@', rawurlencode($INPUT->server->str('HTTP_HOST')), $url); 218 | $url = str_replace('@WIDTH@', $width, $url); 219 | $url = str_replace('@HEIGHT@', $height, $url); 220 | 221 | return $url; 222 | } 223 | 224 | /** 225 | * Extract the wanted size from the parameter list 226 | * 227 | * @param array $params 228 | * @return int[] 229 | */ 230 | public function parseSize(&$params) 231 | { 232 | $known = implode('|', array_keys($this->sizes)); 233 | 234 | foreach (array_keys($params) as $key) { 235 | if (preg_match("/^((\d+)x(\d+))|($known)\$/i", $key, $m)) { 236 | unset($params[$key]); 237 | if (isset($m[4])) { 238 | return $this->sizes[strtolower($m[4])]; 239 | } else { 240 | return [$m[2], $m[3]]; 241 | } 242 | } 243 | } 244 | 245 | // default 246 | return $this->sizes['medium']; 247 | } 248 | 249 | /** 250 | * Get additional attributes to set on the iframe to harden 251 | * 252 | * @link https://dustri.org/b/youtube-video-embedding-harm-reduction.html 253 | * @return array 254 | */ 255 | protected function hardenedIframeAttributes() 256 | { 257 | $disallow = [ 258 | 'accelerometer', 259 | 'ambient-light-sensor', 260 | 'autoplay', 261 | 'battery', 262 | 'browsing-topics', 263 | 'camera', 264 | 'display-capture', 265 | 'domain-agent', 266 | 'document-domain', 267 | 'encrypted-media', 268 | 'execution-while-not-rendered', 269 | 'execution-while-out-of-viewport', 270 | 'gamepad', 271 | 'geolocation', 272 | 'gyroscope', 273 | 'hid', 274 | 'identity-credentials-get', 275 | 'idle-detection', 276 | 'local-fonts', 277 | 'magnetometer', 278 | 'microphone', 279 | 'midi', 280 | 'otp-credentials', 281 | 'payment', 282 | 'picture-in-picture', 283 | 'publickey-credentials-create', 284 | 'publickey-credentials-get', 285 | 'screen-wake-lock', 286 | 'serial', 287 | 'speaker-selection', 288 | 'usb', 289 | 'window-management', 290 | 'xr-spatial-tracking', 291 | ]; 292 | 293 | $disallow = implode('; ', array_map(static fn($v) => "$v 'none'", $disallow)); 294 | 295 | return [ 296 | 'credentialless' => '', 297 | 'sandbox' => 'allow-scripts allow-same-origin', 298 | 'allow' => $disallow, 299 | 'csp' => 'sandbox allow-scripts allow-same-origin', 300 | 'referrerpolicy' => 'no-referrer', 301 | ]; 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/splitbrain/dokuwiki-plugin-vshare/25789cb50418fada66c0fbc0d9b061e0bbb3100b/video.png -------------------------------------------------------------------------------- /video.svg: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------