From f35bd2b4480f6872325626b24a6847270846493f Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 01:03:48 +0100 Subject: [PATCH 01/20] Breaking: Remove closed captions and show related Move also the NodeTypes to own folder --- ...odeTypes.Mixin.Youtube.ClosedCaptions.yaml | 12 --- .../NodeTypes.Mixin.Youtube.ShowRelated.yaml | 12 --- Configuration/Settings.Jonnitto.yaml | 76 ------------------- .../Content/Video.yaml | 2 - .../Mixin/VideoID.yaml | 0 .../Mixin/Youtube/ClosedCaptions.xlf | 12 --- .../NodeTypes/Mixin/Youtube/ShowRelated.xlf | 12 --- .../Mixin/Youtube/ClosedCaptions.xlf | 12 --- .../NodeTypes/Mixin/Youtube/ShowRelated.xlf | 12 --- .../Mixin/Youtube/ClosedCaptions.xlf | 12 --- .../NodeTypes/Mixin/Youtube/ShowRelated.xlf | 12 --- 11 files changed, 174 deletions(-) delete mode 100644 Configuration/NodeTypes.Mixin.Youtube.ClosedCaptions.yaml delete mode 100644 Configuration/NodeTypes.Mixin.Youtube.ShowRelated.yaml delete mode 100644 Configuration/Settings.Jonnitto.yaml rename Configuration/NodeTypes.Content.Video.yaml => NodeTypes/Content/Video.yaml (83%) rename Configuration/NodeTypes.Mixin.VideoID.yaml => NodeTypes/Mixin/VideoID.yaml (100%) delete mode 100644 Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf delete mode 100644 Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ShowRelated.xlf delete mode 100644 Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf delete mode 100644 Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ShowRelated.xlf delete mode 100644 Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf delete mode 100644 Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ShowRelated.xlf diff --git a/Configuration/NodeTypes.Mixin.Youtube.ClosedCaptions.yaml b/Configuration/NodeTypes.Mixin.Youtube.ClosedCaptions.yaml deleted file mode 100644 index 86538ea..0000000 --- a/Configuration/NodeTypes.Mixin.Youtube.ClosedCaptions.yaml +++ /dev/null @@ -1,12 +0,0 @@ -'Jonnitto.PrettyEmbedVideoPlatforms:Mixin.Youtube.ClosedCaptions': - abstract: true - properties: - closedCaptions: - type: boolean - defaultValue: false - ui: - label: i18n - inspector: - group: look - hidden: 'ClientEval:node.properties.platform != "youtube"' - position: 70 diff --git a/Configuration/NodeTypes.Mixin.Youtube.ShowRelated.yaml b/Configuration/NodeTypes.Mixin.Youtube.ShowRelated.yaml deleted file mode 100644 index 67175f5..0000000 --- a/Configuration/NodeTypes.Mixin.Youtube.ShowRelated.yaml +++ /dev/null @@ -1,12 +0,0 @@ -'Jonnitto.PrettyEmbedVideoPlatforms:Mixin.Youtube.ShowRelated': - abstract: true - properties: - showRelated: - type: boolean - defaultValue: false - ui: - label: i18n - inspector: - group: look - hidden: 'ClientEval:node.properties.platform != "youtube"' - position: 80 diff --git a/Configuration/Settings.Jonnitto.yaml b/Configuration/Settings.Jonnitto.yaml deleted file mode 100644 index f78a60b..0000000 --- a/Configuration/Settings.Jonnitto.yaml +++ /dev/null @@ -1,76 +0,0 @@ -Jonnitto: - PrettyEmbedVideoPlatforms: - enableJsApi: false - loadImageStrategy: lazy - defaults: - # Should the video be opened on a lightbox? Per default this is set via the node properties - lightbox: false - - # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties - preserveAspectRatio: true - - # If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9. Per default this is set via the node properties - force16to9: true - - # Whether to restart the video automatically after reaching the end. - loop: false - - # Whether the video plays inline on supported mobile devices. - # Note that if set to false it does not imply that the video will always be played in fullscreen. - playsinline: true - - # Allow full screen - allowFullScreen: true - - ################################# - # Additional settings for Youtube - ################################# - - # This parameter indicates whether the video player controls are displayed - controls: true - - # Setting the parameter's value to true causes closed captions to be shown by default, even if the user has turned captions off. - closedCaptions: false - - # It is not possible to disable related videos, but if it is set to false, the player will - # show related videos that are from the same channel as the video that was just played. - showRelated: false - - ############################### - # Additional settings for Vimeo - ############################### - - # Whether to pause the current video when another Vimeo video on the same page starts to play. - # Set this value to false to permit simultaneous playback of all the videos on the page. - autopause: true - - # Whether the player is in background mode, which hides the playback controls, enables autoplay, and loops the video. - background: false - - # Whether the video is muted upon loading. The true value is required for the autoplay behavior in some browsers. - muted: false - - # Whether the responsive player and transparent background are enabled - transparent: true - - # The hexadecimal color value of the playback controls, which is normally 00ADEF. - color: false - - # Whether the player displays the title overlay - previewTitle: false - - # Whether to display the video owner's name. - previewByline: false - - # Whether to display the video owner's portrait. - previewPortrait: false - youtube: - playlist: - embed: 'https://www.youtube-nocookie.com/embed/videoseries?list=%id%' - href: 'https://www.youtube.com/playlist?list=%id%' - video: - embed: 'https://www.youtube-nocookie.com/embed/%id%' - href: 'https://www.youtube.com/watch?v=%id%' - vimeo: - embed: 'https://player.vimeo.com/video/%id%' - href: 'https://vimeo.com/%id%' diff --git a/Configuration/NodeTypes.Content.Video.yaml b/NodeTypes/Content/Video.yaml similarity index 83% rename from Configuration/NodeTypes.Content.Video.yaml rename to NodeTypes/Content/Video.yaml index 232262d..c8ee2fd 100644 --- a/Configuration/NodeTypes.Content.Video.yaml +++ b/NodeTypes/Content/Video.yaml @@ -13,8 +13,6 @@ # 'Jonnitto.PrettyEmbedHelper:Mixin.AllowFullScreen': true # 'Jonnitto.PrettyEmbedHelper:Mixin.Loop': true # 'Jonnitto.PrettyEmbedHelper:Mixin.Controls': true - # 'Jonnitto.PrettyEmbedVideoPlatforms:Mixin.Youtube.ClosedCaptions': true - # 'Jonnitto.PrettyEmbedVideoPlatforms:Mixin.Youtube.ShowRelated': true ui: label: 'Vimeo / YouTube' icon: play-circle diff --git a/Configuration/NodeTypes.Mixin.VideoID.yaml b/NodeTypes/Mixin/VideoID.yaml similarity index 100% rename from Configuration/NodeTypes.Mixin.VideoID.yaml rename to NodeTypes/Mixin/VideoID.yaml diff --git a/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf b/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf deleted file mode 100644 index 4e53c65..0000000 --- a/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display closed captions (if available) - Zeige Untertitel (sofern verfügbar) - - - - diff --git a/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ShowRelated.xlf b/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ShowRelated.xlf deleted file mode 100644 index 761d126..0000000 --- a/Resources/Private/Translations/de/NodeTypes/Mixin/Youtube/ShowRelated.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display related videos on video end - Zeige ähnliche Videos am Videoende - - - - diff --git a/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf b/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf deleted file mode 100644 index f8a9f0c..0000000 --- a/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display closed captions (if available) - Display closed captions (if available) - - - - diff --git a/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ShowRelated.xlf b/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ShowRelated.xlf deleted file mode 100644 index eddff8e..0000000 --- a/Resources/Private/Translations/en/NodeTypes/Mixin/Youtube/ShowRelated.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display related videos on video end - Display related videos on video end - - - - diff --git a/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf b/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf deleted file mode 100644 index 51d0095..0000000 --- a/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ClosedCaptions.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display closed captions (if available) - Afficher les sous-titres (si disponibles) - - - - diff --git a/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ShowRelated.xlf b/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ShowRelated.xlf deleted file mode 100644 index 4c9c6b0..0000000 --- a/Resources/Private/Translations/fr/NodeTypes/Mixin/Youtube/ShowRelated.xlf +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Display related videos on video end - Afficher les vidéos associées à la fin de la vidéo - - - - From f52dbed1c5ec91fe2bb7cdb388f704002827dc17 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 01:09:37 +0100 Subject: [PATCH 02/20] Docs: First adjustments --- README.md | 187 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 129 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index f438c7b..78aa1f7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ Prettier embeds for your Vimeo videos and YouTube videos/playlists in [Neos CMS] | ------- | ----------- | :--------: | | 1.\* | 4.2.\*, > 5 | ✗ | | 2.\* | >= 5.3 | ✗ | -| 3.\* | >= 5.3 | ✓ | +| 3.\* | >= 5.3 | ✗ | +| 4.\* | >= 7.3 | ✓ | ## Installation @@ -35,74 +36,147 @@ The `--no-update` command prevent the automatic update of the dependencies. Afte | Preview image | ✓ | | | Lightbox included | ✓ | | | Preview image (for videos) | ✓ | | -| Javascript API | | ✓ | +| Javascript API | ✓ | ✓ | | Filesize (JS & CSS) | smaller | bigger | All packages from the PrettyEmbed series have the benefit of a better frontend performance since the player gets only loaded on request. So, no iframe/video gets loaded until the user wants to watch a video. ## Customization -### [Settings.Jonnitto.yaml] +### Global settings for the whole PrettyEmbed series -#### JS API / Usage of youtube-nocookie.com - -If you want to use the JavaScript API from YouTube or Vimeo (e.g., for tracking), you have to enable set `enableJsApi` to `true`. - -```yaml -Jonnitto: - PrettyEmbedVideoPlatforms: - enableJsApi: true -``` - -per default, the youtube-nocookie.com domain is used for embedding YouTube videos. +The settings will be set globally from the [PrettyEmbedHelper] package. These are the default settings: ```yaml Jonnitto: - PrettyEmbedVideoPlatforms: - youtube: - playlist: - embed: 'https://www.youtube-nocookie.com/embed/videoseries?list=%id%' - href: 'https://www.youtube.com/playlist?list=%id%' - video: - embed: 'https://www.youtube-nocookie.com/embed/%id%' - href: 'https://www.youtube.com/watch?v=%id%' -``` - -Be aware that you need to provide the placeholder for the ID (`%id%`) of the playlist or video. - -#### Global settings for the whole PrettyEmbed series + PrettyEmbed: + # If you have your own AlpineJS in your setup, you can disable the check here. Alpine must be an global variable + includeAlpineJsCheck: true -Some settings will be set globally from the [PrettyEmbedHelper] package. These are the default settings: - -```yaml -Jonnitto: - PrettyEmbedHelper: - # If you want to use your own assets, set this to false (Backend.js and Backend.css will be always be included in the backend) + # If you want to use your own assets, set this to false (Backend.Video.css ignores this setting) includeAssets: css: true js: true - # If you want to save the duration of YouTube videos and playlists into the - # property metadataDuration you have to add a API key from YouTube Data API v3 - # You can create this key on https://console.cloud.google.com/ - youtubeApiKey: null - - # For Vimeo and Youtube you can enable here the option the show a confirm dialog - # that external content get loaded and the user may be tracked - enableGdprMessage: false - - # This is the maximum width of a custom preview image - maximumWidth: 1920 + # Can be `lazy`, `eager` or `null` + loadImageStrategy: lazy # If this is set to a string, the element gets wrapped with a div and the class with the giving string. # If set to true, the element gets wrapped with a div without any class. # If set to false, the element get not wrapped at all - wrapper: 'jonnitto-prettyembed-wrapper' + wrapper: false # The buttons which get injected (file content) to the player. + # You can also overwrite the button Fusion components button: play: 'resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PlayButton.svg' pause: 'resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PauseButton.svg' + + # This is the maximum width of a custom preview image + maximumWidth: 1920 + + # Settings for the vimeo player + Vimeo: + # Set to `false` to disable the gdpr message, set to `popup` open the video in a new window or set to `true` to show the message in the player + gdprHandling: true + + # The hexadecimal color value of the playback controls, which is normally 00ADEF. + color: false + + # Show the controls or not + controls: true + + # Whether the player is in background mode, which hides the playback controls, enables autoplay, and loops the video. + background: false + + # Whether to restart the video automatically after reaching the end. + loop: false + + # Should the video be opened on a lightbox? Per default this is set via the node properties + lightbox: false + + # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties + preserveAspectRatio: true + + # If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9. Per default this is set via the node properties + force16to9: true + + YouTube: + # Set to false to disable the gdpr message, set to popup open the video in a new window or set to true to show the message in the player + gdprHandling: true + + # If you want to save the duration of YouTube videos and playlists into the + # property metadataDuration you have to add a API key from YouTube Data API v3 + # You can create this key on https://console.cloud.google.com/ + # This key is only used in the backend + apiKey: null + + # Show the controls or not + controls: true + + # Whether to restart the video automatically after reaching the end. + loop: false + + # Should the video be opened on a lightbox? Per default this is set via the node properties + lightbox: false + + # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties + preserveAspectRatio: true + + # If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9. Per default this is set via the node properties + force16to9: true + + Video: + # If true, the browser will offer controls to allow the user to control + # video playback, including volume, seeking, and pause/resume playback. + controls: true + + # Should the video be opened on a lightbox? Per default this is set via the node properties + lightbox: false + + # If true, the video automatically begins to play back as soon + # as it can do so without stopping to finish loading the data. + autoplay: false + + # If true, the browser will automatically seek back + # to the start upon reaching the end of the video. + loop: false + + # Whether the video is muted upon loading. Set automatically to true if autoplay is enabled + muted: false + + # This enumerated attribute is intended to provide a hint to the browser about what + # the author thinks will lead to the best user experience with regards to what content + # is loaded before the video is played. It may have one of the following values: + # - none Indicates that the video should not be preloaded. + # - metadata Indicates that only video metadata (e.g. length) is fetched. + # - auto Indicates that the whole video file can be downloaded, even if the user is not expected to use it + preload: none + + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-crossorigin + # anonymous || use-credentials || true || false + crossorigin: false + + Audio: + # If true, the browser will offer controls to allow the user to control + # audio playback, including volume, seeking, and pause/resume playback. + controls: true + + # If true, the browser will automatically seek back + # to the start upon reaching the end of the audio. + loop: false + + # This enumerated attribute is intended to provide a hint to the browser about what + # the author thinks will lead to the best user experience with regards to what content + # is loaded before the audio is played. It may have one of the following values: + # - none Indicates that the audio should not be preloaded. + # - metadata Indicates that the browser should load only metadata when the page loads + # - auto Indicates that the whole audio file can be downloaded, even if the user is not expected to use it + preload: metadata + + # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio#attr-crossorigin + # anonymous || use-credentials || true || false + crossorigin: false ``` #### Disable inclusion of the CSS and/or JS files @@ -113,7 +187,7 @@ If you want to load your own CSS, you can disable it like that: ```yaml Jonnitto: - PrettyEmbedHelper: + PrettyEmbed: includeAssets: css: false ``` @@ -122,7 +196,7 @@ If you want to load your own Javascript, you can disable it like that: ```yaml Jonnitto: - PrettyEmbedHelper: + PrettyEmbed: includeAssets: js: false ``` @@ -194,15 +268,15 @@ them before you import [`Main.scss`]. Like that, most of the frequent adjustment ### NodeTypes and Mixins -If you want to customize the default settings, take a look at the [Settings.Jonnitto.yaml] file. -If no node property is given, these default values will be taken. If you, for example, want to let -the editor choose if the video is allowed to play the video in fullscreen or not, you can activate -the mixin in your Configuration folder like this: +If you want to customize the default settings, take a look at the `Settings.Jonnitto.yaml` from [PrettyEmbedHelper] +file. If no node property is given, these default values will be taken. If you, for example, want to let the editor +choose if the video is has the controls from the platform, you can activate the mixin in your file where you override +node types like that: ```yaml 'Jonnitto.PrettyEmbedVideoPlatforms:Content.Video': superTypes: - 'Jonnitto.PrettyEmbedHelper:Mixin.AllowFullScreen': true + 'Jonnitto.PrettyEmbedHelper:Mixin.Controls': true ``` These are the available mixins: @@ -218,8 +292,6 @@ These are the available mixins: | `Helper:Mixin.AllowFullScreen` | Allow fullscreen or not | `true` | | | `Helper:Mixin.Loop` | Loop the video | `false` | | | `Helper:Mixin.Controls` | Show the controls | `true` | | -| `PrettyEmbedVideoPlatforms:Mixin.Youtube.ClosedCaptions` | Show captions | `false` | | -| `PrettyEmbedVideoPlatforms:Mixin.Youtube.ShowRelated` | If `false`, show only related videos that are from the same channel | `false` | | If you want to include the video in your node type, you should use at least the mixin `Jonnitto.PrettyEmbedVideoPlatforms:Mixin.VideoID`. This add besides the `videoID` property also the properties for the metadata fetched from the oembed service. This mixin is also necessary to fetch/update the data from the service. @@ -233,7 +305,7 @@ If you want to parse existing content with iframes and replace them automaticall ## Get metadata -To get the metadata, you can run the flow command `./flow prettyembed:metadata`. This command search for nodes with the `VideoID` mixin, and tries to get the metadata. If for some reason, it is not possible to fetch the metadata (Perhaps the video is set to private, or the ID does not exist), you will get a table with the name of the node type, the type, the video ID and the node path. +To get the metadata, you can run the flow command `./flow prettyembed:metadata`. This command search for nodes with the `VideoID` mixin, and tries to get the metadata. If for some reason, it is not possible to fetch the metadata (Perhaps the video is set to private, or the ID does not exist), you will get a table with the name of the node type, the type, the video ID and the node path. The task comes with two options: - `--workspace` Workspace name, default is 'live' @@ -244,10 +316,10 @@ To get an overview of the options in the cli, you can run `./flow help prettyemb ## Merge PrettyEmbedYoutube and PrettyEmbedVimeo If you want existing nodes from [PrettyEmbedYoutube] and [PrettyEmbedVimeo] use this package, -you have to run following command in your cli: +you have to run following command in your cli: `./flow node:migrate --version 20200420033756` -After this migration you have to flush your frontend cache: +After this migration you have to flush your frontend cache: `./flow cache:flushone --identifier Neos_Fusion_Content` ## PrettyEmbedCollection @@ -285,7 +357,6 @@ If you install the PrettyEmbedCollection, the video players get grouped into an [prettyembedvideo]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideo [prettyembedvideoplatforms]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideoPlatforms [jonnitto.plyr]: https://github.com/jonnitto/Jonnitto.Plyr -[settings.jonnitto.yaml]: Configuration/Settings.Jonnitto.yaml [`jonnitto.prettyembedvideoplatforms:component.video`]: Resources/Private/Fusion/Component/Video.fusion [`jonnitto.prettyembedvideoplatforms:content.video`]: Resources/Private/Fusion/Content/Video.fusion [`jonnitto.prettyembedvideoplatforms:replaceiframes`]: Resources/Private/Fusion/ReplaceIframes.fusion From 514b12af3357ffa00fe4872e2705099f3e8819ce Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 01:10:04 +0100 Subject: [PATCH 03/20] Breaking: Raise dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ffe82a9..aa6fca7 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ } ], "require": { - "jonnitto/prettyembedhelper": "^4.3 || dev-master" + "jonnitto/prettyembedhelper": "^5.0 || dev-master" }, "autoload": { "psr-4": { From 38d1d6cba7bd153de9af2160f799a78790351558 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 01:10:22 +0100 Subject: [PATCH 04/20] Update: Remove origin property --- Classes/FusionObjects/ReplaceIframesImplementation.php | 9 --------- .../Private/Fusion/Component/Attribute.Embed.fusion | 1 - Resources/Private/Fusion/Component/Video/Video.fusion | 1 - Resources/Private/Fusion/Content/Video.fusion | 1 - Resources/Private/Fusion/ReplaceIframes.fusion | 7 ------- 5 files changed, 19 deletions(-) diff --git a/Classes/FusionObjects/ReplaceIframesImplementation.php b/Classes/FusionObjects/ReplaceIframesImplementation.php index 2758d82..e9905e1 100644 --- a/Classes/FusionObjects/ReplaceIframesImplementation.php +++ b/Classes/FusionObjects/ReplaceIframesImplementation.php @@ -31,14 +31,6 @@ public function getContent(): string return (string) $this->fusionValue('content'); } - /** - * @return string - */ - public function getOrigin(): string - { - return (string) $this->fusionValue('origin'); - } - /** * Render Replace embeded iframes with the pretty embeded markup * @@ -100,7 +92,6 @@ protected function buildYoutube(string $videoID, string $type): string 'videoID' => $videoID, 'type' => $type, 'poster' => $poster, - 'origin' => $this->getOrigin(), ]); $html = $this->runtime->render($this->path . '/itemYoutubeRenderer'); $this->runtime->popContext(); diff --git a/Resources/Private/Fusion/Component/Attribute.Embed.fusion b/Resources/Private/Fusion/Component/Attribute.Embed.fusion index 0e953ba..f32a1d5 100644 --- a/Resources/Private/Fusion/Component/Attribute.Embed.fusion +++ b/Resources/Private/Fusion/Component/Attribute.Embed.fusion @@ -40,7 +40,6 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes.Embed) < proto closedCaptions = ${props.closedCaptions ? '&cc_load_policy=1' : ''} showRelated = ${props.showRelated ? '&rel=1' : '&rel=0'} fullscreen = ${props.allowFullScreen ? '' : '&fs=0'} - origin = ${props.origin ? '&origin=' + props.origin : ''} additionalValues = ${props.additionalValues ? '&' + props.additionalValues : ''} } } diff --git a/Resources/Private/Fusion/Component/Video/Video.fusion b/Resources/Private/Fusion/Component/Video/Video.fusion index e7340f4..4ea6f16 100644 --- a/Resources/Private/Fusion/Component/Video/Video.fusion +++ b/Resources/Private/Fusion/Component/Video/Video.fusion @@ -38,7 +38,6 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Video) < prototype(Neos.F poster = ${null} poster2x = ${null} alternativeText = ${null} - origin = ${null} playButton = Jonnitto.PrettyEmbedHelper:Button.Play diff --git a/Resources/Private/Fusion/Content/Video.fusion b/Resources/Private/Fusion/Content/Video.fusion index ddce1f5..3055dc6 100644 --- a/Resources/Private/Fusion/Content/Video.fusion +++ b/Resources/Private/Fusion/Content/Video.fusion @@ -125,7 +125,6 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto These properties are already defined in Jonnitto.PrettyEmbedHelper:Content - maximumWidth - wrapper - - origin - image */ diff --git a/Resources/Private/Fusion/ReplaceIframes.fusion b/Resources/Private/Fusion/ReplaceIframes.fusion index e8a3235..47effaa 100644 --- a/Resources/Private/Fusion/ReplaceIframes.fusion +++ b/Resources/Private/Fusion/ReplaceIframes.fusion @@ -4,19 +4,12 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { // The content to parse content = ${value} - origin = Neos.Neos:NodeUri { - node = ${site} - absolute = true - @process.onlyTheDomain = ${String.pregMatch(value, '(https?:\/\/[^\/]+)')[0]} - } - // This property is used internally by `ReplaceIframesImplementation` to render each YouTube iframe. // It can be modified to change behaviour for all rendered YouTube items. itemYoutubeRenderer = Jonnitto.PrettyEmbedVideoPlatforms:Component.Video { type = ${type} videoID = ${videoID} platform = 'youtube' - origin = ${origin} poster = ${poster} // Set this to replace the preview image From 6ae61b1a8dde7bea6c196312dc8046ffa56a6466 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 20:27:36 +0100 Subject: [PATCH 05/20] Update: Use updated utility functions --- .../ReplaceIframesImplementation.php | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/Classes/FusionObjects/ReplaceIframesImplementation.php b/Classes/FusionObjects/ReplaceIframesImplementation.php index e9905e1..cbf91c4 100644 --- a/Classes/FusionObjects/ReplaceIframesImplementation.php +++ b/Classes/FusionObjects/ReplaceIframesImplementation.php @@ -2,7 +2,6 @@ namespace Jonnitto\PrettyEmbedVideoPlatforms\FusionObjects; -use Jonnitto\PrettyEmbedHelper\Service\ApiService; use Jonnitto\PrettyEmbedHelper\Service\ParseIDService; use Jonnitto\PrettyEmbedHelper\Service\YoutubeService; use Jonnitto\PrettyEmbedHelper\Utility\Utility; @@ -82,12 +81,7 @@ public function evaluate(): string protected function buildYoutube(string $videoID, string $type): string { - $data = $this->youtubeService->getBestPossibleYoutubeImage($videoID); - $poster = null; - if (isset($data)) { - $utility = new Utility(); - $poster = $utility->removeProtocolFromUrl($data['image'] ?? null); - } + $poster = Utility::youtubeThumbnail($videoID); $this->runtime->pushContextArray([ 'videoID' => $videoID, 'type' => $type, @@ -100,14 +94,7 @@ protected function buildYoutube(string $videoID, string $type): string protected function buildVimeo(string $videoID): string { - $api = new ApiService(); - $data = $api->vimeo($videoID); - $poster = null; - if (isset($data)) { - $utility = new Utility(); - $poster = $utility->removeProtocolFromUrl($data['thumbnail_url'] ?? null); - } - + $poster = Utility::vimeoThumbnail($videoID); $this->runtime->pushContextArray([ 'videoID' => $videoID, 'poster' => $poster From 9abd901b995ff0c64fbf02a4d8deba0438dea8e8 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 20:28:39 +0100 Subject: [PATCH 06/20] Update: Ignore .vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode From 471f83be23561eb468031e614a497039d4a80f25 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 20:29:19 +0100 Subject: [PATCH 07/20] Breaking: Remove components --- .../Fusion/Component/Attribute.Embed.fusion | 47 ----- .../Fusion/Component/Attributes.fusion | 27 --- .../Component/Video/Fragment/Vimeo.fusion | 18 -- .../Component/Video/Fragment/Youtube.fusion | 18 -- .../Fusion/Component/Video/Video.fusion | 86 -------- Resources/Private/Fusion/Content/Video.fusion | 189 ------------------ 6 files changed, 385 deletions(-) delete mode 100644 Resources/Private/Fusion/Component/Attribute.Embed.fusion delete mode 100644 Resources/Private/Fusion/Component/Attributes.fusion delete mode 100644 Resources/Private/Fusion/Component/Video/Fragment/Vimeo.fusion delete mode 100644 Resources/Private/Fusion/Component/Video/Fragment/Youtube.fusion delete mode 100644 Resources/Private/Fusion/Component/Video/Video.fusion delete mode 100644 Resources/Private/Fusion/Content/Video.fusion diff --git a/Resources/Private/Fusion/Component/Attribute.Embed.fusion b/Resources/Private/Fusion/Component/Attribute.Embed.fusion deleted file mode 100644 index f32a1d5..0000000 --- a/Resources/Private/Fusion/Component/Attribute.Embed.fusion +++ /dev/null @@ -1,47 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes.Embed) < prototype(Neos.Fusion:Component) { - configuration = ${Configuration.setting('Jonnitto.PrettyEmbedVideoPlatforms')} - url = ${this.platform == 'youtube' ? this.configuration.youtube[this.type] : this.configuration[this.platform]} - additionalValues = ${null} - - @of.hasNeededProperties = ${this.platform && this.videoID && Type.isArray(this.url) && Type.isString(this.url.embed)} - - renderer = Neos.Fusion:Case { - isVimeo { - condition = ${props.platform == 'vimeo'} - renderer = Neos.Fusion:Join { - src = ${String.replace(props.url.embed, '%id%', props.videoID)} - connect = ${String.indexOf(props.url.embed, '?') == -1 ? '?' : '&'} - autoplay = 'autoplay=1' - loop = ${props.loop ? '&loop=1' : ''} - color = ${props.color ? '&color=' + String.replace(props.color, '#', '') : ''} - autopause = ${props.autopause ? '' : '&autopause=0'} - background = ${props.background ? '' : '&background=0'} - muted = ${props.muted ? '&muted=1' : ''} - playsinline = ${props.playsinline ? '' : '&playsinline=0'} - transparent = ${props.transparent ? '' : '&transparent=0'} - previewTitle = ${props.previewTitle ? '' : '&title=0'} - previewByline = ${props.previewByline ? '' : '&byline=0'} - previewPortrait = ${props.previewPortrait ? '' : '&portrait=0'} - additionalValues = ${props.additionalValues ? '&' + props.additionalValues : ''} - } - } - isYoutube { - condition = ${props.platform == 'youtube'} - renderer = Neos.Fusion:Join { - src = ${String.replace(props.url.embed, '%id%', props.videoID)} - connect = ${String.indexOf(props.url.embed, '?') == -1 ? '?' : '&'} - autoplay = 'autoplay=1' - modestbranding = '&modestbranding=1' - enableJsApi = ${props.enableJsApi ? '&enablejsapi=1' : ''} - playsinline = ${'&playsinline=' + (props.playsinline ? '1' : '0')} - controls = ${props.controls ? '' : '&controls=0'} - loop = ${props.loop ? '&loop=1' : ''} - muted = ${props.muted ? '&mute=1' : ''} - closedCaptions = ${props.closedCaptions ? '&cc_load_policy=1' : ''} - showRelated = ${props.showRelated ? '&rel=1' : '&rel=0'} - fullscreen = ${props.allowFullScreen ? '' : '&fs=0'} - additionalValues = ${props.additionalValues ? '&' + props.additionalValues : ''} - } - } - } -} diff --git a/Resources/Private/Fusion/Component/Attributes.fusion b/Resources/Private/Fusion/Component/Attributes.fusion deleted file mode 100644 index 957f494..0000000 --- a/Resources/Private/Fusion/Component/Attributes.fusion +++ /dev/null @@ -1,27 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes) < prototype(Neos.Fusion:Component) { - renderer = Neos.Fusion:Attributes { - id = ${props.id} - class = Carbon.Eel:BEM { - block = 'jonnitto-prettyembed' - modifier = Neos.Fusion:DataStructure { - platform = ${props.platform} - iframe = true - ratio = ${props.hasLightboxWithPreserveAspectRatio ? null : !!props.finalRatio} - look = ${props.look} - } - } - href = ${String.replace(props.url.href, '%id%', props.videoID)} - rel = 'noopener' - target = '_blank' - style = ${!props.hasLightboxWithPreserveAspectRatio && props.finalRatio ? 'padding-top:' + props.finalRatio : null} - aria-label = ${props.metadataTitle} - data-gdpr = ${props.enableGdprMessage && props.gdprMessage ? props.gdprMessage : null} - data-gdpr-accept = ${props.enableGdprMessage && props.gdprMessageAccept ? props.gdprMessageAccept : null} - data-gdpr-new-window = ${props.enableGdprMessage && props.gdprMessageNewWindow ? props.gdprMessageNewWindow : null} - data-ratio = ${props.finalRatio || null} - data-fs = ${!!props.allowFullScreen} - data-embed = Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes.Embed { - @apply.props = ${props} - } - } -} diff --git a/Resources/Private/Fusion/Component/Video/Fragment/Vimeo.fusion b/Resources/Private/Fusion/Component/Video/Fragment/Vimeo.fusion deleted file mode 100644 index b9c7c32..0000000 --- a/Resources/Private/Fusion/Component/Video/Fragment/Vimeo.fusion +++ /dev/null @@ -1,18 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Video.Fragment.Vimeo) < prototype(Neos.Fusion:Component) { - renderer = Neos.Fusion:Tag { - tagName = ${props.live ? 'a' : 'div'} - attributes = Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes { - @apply.props = ${props} - } - content = afx` - - {props.playButton} - {props.content} - {props.alternativeText} - ` - - @process.wrapper = Jonnitto.PrettyEmbedHelper:Wrapper { - wrapper = ${props.wrapper} - } - } -} diff --git a/Resources/Private/Fusion/Component/Video/Fragment/Youtube.fusion b/Resources/Private/Fusion/Component/Video/Fragment/Youtube.fusion deleted file mode 100644 index ab06a50..0000000 --- a/Resources/Private/Fusion/Component/Video/Fragment/Youtube.fusion +++ /dev/null @@ -1,18 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Video.Fragment.Youtube) < prototype(Neos.Fusion:Component) { - renderer = Neos.Fusion:Tag { - tagName = ${props.live ? 'a' : 'div'} - attributes = Jonnitto.PrettyEmbedVideoPlatforms:Component.Attributes { - @apply.props = ${props} - } - content = afx` - - {props.playButton} - {props.content} - {props.alternativeText} - ` - - @process.wrapper = Jonnitto.PrettyEmbedHelper:Wrapper { - wrapper = ${props.wrapper} - } - } -} diff --git a/Resources/Private/Fusion/Component/Video/Video.fusion b/Resources/Private/Fusion/Component/Video/Video.fusion deleted file mode 100644 index 4ea6f16..0000000 --- a/Resources/Private/Fusion/Component/Video/Video.fusion +++ /dev/null @@ -1,86 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Component.Video) < prototype(Neos.Fusion:Component) { - configuration = ${Configuration.setting('Jonnitto.PrettyEmbedVideoPlatforms')} - - // This can used as alternative preview - content = ${null} - - live = true - platform = ${null} - videoID = ${null} - videoID.@process.trim = ${Type.isString(value) ? String.trim(value) : value} - - lightbox = ${this.configuration.defaults.lightbox} - preserveAspectRatio = ${this.configuration.defaults.preserveAspectRatio} - allowFullScreen = ${this.configuration.defaults.allowFullScreen} - - controls = ${this.configuration.defaults.controls} - loop = ${this.configuration.defaults.loop} - - playsinline = ${this.configuration.defaults.playsinline} - enableJsApi = ${this.configuration.enableJsApi} - loadImageStrategy = ${this.configuration.loadImageStrategy} - enableGdprMessage = ${Configuration.setting('Jonnitto.PrettyEmbedHelper.enableGdprMessage')} - gdprMessage = Jonnitto.PrettyEmbedHelper:GdprMessage - gdprMessageAccept = Jonnitto.PrettyEmbedHelper:GdprMessageAccept - gdprMessageNewWindow = Jonnitto.PrettyEmbedHelper:GdprMessageNewWindow - - // Pass a ratio like this: ${16 / 9} - ratio = ${null} - - // If true, this get only a value if ratio is not set - force16to9 = ${this.configuration.defaults.force16to9} - force16to9.@process.setRatio = ${value ? (16 / 9) : null} - - wrapper = ${Configuration.setting('Jonnitto.PrettyEmbedHelper.wrapper')} - - id = ${null} - - poster = ${null} - poster2x = ${null} - alternativeText = ${null} - - playButton = Jonnitto.PrettyEmbedHelper:Button.Play - - // YouTube specific - type = ${null} - closedCaptions = ${this.configuration.defaults.closedCaptions} - showRelated = ${this.configuration.defaults.showRelated} - - // Vimeo specific - color = ${this.configuration.defaults.color} - autopause = ${this.configuration.defaults.autopause} - background = ${this.configuration.defaults.background} - muted = ${this.configuration.defaults.muted} - transparent = ${this.configuration.defaults.transparent} - previewTitle = ${this.configuration.defaults.previewTitle} - previewByline = ${this.configuration.defaults.previewByline} - previewPortrait = ${this.configuration.defaults.previewPortrait} - - - // Internal - isYouTube = ${this.platform == 'youtube'} - look = ${this.lightbox ? 'lightbox' : 'inline'} - url = ${this.isYouTube ? this.configuration.youtube[this.type] : this.configuration[this.platform]} - hasLightboxWithPreserveAspectRatio = ${this.lightbox && this.preserveAspectRatio} - finalRatio = ${Jonnitto.PrettyEmbedHelper.paddingTop(this.ratio || this.force16to9)} - - previewImageClass = ${!this.poster && this.isYouTube ? 'jonnitto-prettyembed__youtube-preview' : null} - posterFromYoutube = ${this.isYouTube && this.type == 'video' && !this.poster ? '//i.ytimg.com/vi/' + this.videoID + '/maxresdefault.jpg' : null} - posterFromVimeo = ${this.platform == 'vimeo' && !this.poster ? Jonnitto.PrettyEmbedHelper.vimeoThumbnail(this.videoID) : null} - finalPoster = ${this.poster || this.posterFromYoutube || this.posterFromVimeo} - - @if.hasNeededProperties = ${this.platform && this.videoID && (this.finalPoster || this.content) && (this.isYouTube ? !!this.platform : true)} - - renderer = afx` - - - ` -} diff --git a/Resources/Private/Fusion/Content/Video.fusion b/Resources/Private/Fusion/Content/Video.fusion deleted file mode 100644 index 3055dc6..0000000 --- a/Resources/Private/Fusion/Content/Video.fusion +++ /dev/null @@ -1,189 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto.PrettyEmbedHelper:Content) { - package = 'VideoPlatforms' - - platform = ${q(node).property('platform')} - type = ${q(node).property('type')} - videoID = ${q(node).property('videoID')} - - metadataID = ${q(node).property('metadataID')} - metadataTitle = ${q(node).property('metadataTitle')} - alternativeText = ${this.metadataTitle} - imageFromPlatform = ${q(node).property('metadataImage')} - thumbnailFromResources = ${q(node).property('metadataThumbnail')} - ratio = ${q(node).property('metadataRatio')} - async = true - - // This can used as alternative preview - content = ${null} - - loadImageStrategy = ${Configuration.setting('Jonnitto.PrettyEmbedVideoPlatforms.loadImageStrategy')} - enableGdprMessage = ${Configuration.setting('Jonnitto.PrettyEmbedHelper.enableGdprMessage')} - gdprMessage = Jonnitto.PrettyEmbedHelper:GdprMessage - gdprMessageAccept = Jonnitto.PrettyEmbedHelper:GdprMessageAccept - gdprMessageNewWindow = Jonnitto.PrettyEmbedHelper:GdprMessageNewWindow - - showBackendNotification = true - - // Should the video be opened on a lightbox? - lightbox = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'lightbox' - } - - // When the lightbox is set, should the preview image preserve his aspect ratio? - preserveAspectRatio = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'preserveAspectRatio' - } - - // If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9 - force16to9 = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'force16to9' - } - - // Whether to restart the video automatically after reaching the end. - loop = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'loop' - } - - // Whether the video plays inline on supported mobile devices. - // Note that if set to false it does not imply that the video will always be played in fullscreen. - playsinline = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'playsinline' - } - - // Allow full screen - allowFullScreen = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'allowFullScreen' - } - - ////////////////////////////////// - // Additional settings for Youtube - ////////////////////////////////// - - // This parameter indicates whether the video player controls are displayed - controls = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'controls' - } - - // Setting the parameter's value to true causes closed captions to be shown by default, - // even if the user has turned captions off. - closedCaptions = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'closedCaptions' - } - - // It is not possible to disable related videos, but if it is set to false, the player will - // show related videos that are from the same channel as the video that was just played. - showRelated = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'showRelated' - } - - //////////////////////////////// - // Additional settings for Vimeo - //////////////////////////////// - - // Whether to pause the current video when another Vimeo video on the same page starts to play. - // Set this value to false to permit simultaneous playback of all the videos on the page. - autopause = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'autopause' - } - - // Whether the player is in background mode, which hides the playback controls, enables autoplay, and loops the video. - background = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'background' - } - - // Whether the video is muted upon loading. The true value is required for the autoplay behavior in some browsers. - muted = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'muted' - } - - // Whether the responsive player and transparent background are enabled - transparent = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'transparent' - } - - // The hexadecimal color value of the playback controls, which is normally 00ADEF. - color = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'color' - } - - // Whether the player displays the title overlay - previewTitle = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'previewTitle' - } - - // Whether to display the video owner's name. - previewByline = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'previewByline' - } - - // Whether to display the video owner's portrait. - previewPortrait = Jonnitto.PrettyEmbedHelper:GetProperty { - property = 'previewPortrait' - } - - /* - These properties are already defined in Jonnitto.PrettyEmbedHelper:Content - - maximumWidth - - wrapper - - image - */ - - // Internal - videoID.@process.getIDFromUrl = ${this.metadataID ? this.metadataID : (value && this.platform ? Jonnitto.PrettyEmbedHelper.platformID(value, this.platform) : value)} - - renderer = Neos.Fusion:Component { - @apply.props = ${props} - poster = Neos.Fusion:Case { - hasAlternativePreview { - condition = ${props.content} - renderer = true - } - hasPersistentResource { - condition = ${props.image || props.thumbnailFromResources} - renderer = Neos.Neos:ImageUri { - asset = ${props.image || props.thumbnailFromResources} - async = ${props.async} - maximumWidth = ${props.maximumWidth} - } - } - imageFromVimeo { - condition = ${props.videoID && props.platform == 'vimeo'} - renderer = ${props.imageFromPlatform || Jonnitto.PrettyEmbedHelper.vimeoThumbnail(props.videoID)} - } - imageFromPlatform { - condition = ${props.videoID} - renderer = ${props.imageFromPlatform} - } - } - poster2x = Neos.Neos:ImageUri { - @if { - hasAsset = ${this.asset} - hasEnoughPixel = ${this.asset.width >= props.maximumWidth * 2} - } - asset = ${props.image || props.thumbnailFromResources} - async = ${props.async} - maximumWidth = ${props.maximumWidth * 2} - } - renderer = Neos.Fusion:Case { - noVideoID { - condition = ${!props.videoID || !props.platform} - renderer = Jonnitto.PrettyEmbedHelper:Notification { - @if.set = ${props.showBackendNotification} - key = 'noVideoID' - default = 'Please add a Video URL / ID or url in the inspector' - } - } - noPoster { - condition = ${!props.poster && (props.platform == 'youtube' ? props.type == 'playlist' : true)} - renderer = Jonnitto.PrettyEmbedHelper:Notification { - key = 'needPreviewImage' - default = 'You need to define a custom preview image.' - } - } - default { - condition = true - renderer = afx`` - } - } - } -} From 560bad8e811aba09e8928c8157eefd49c8f3726e Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 23:26:34 +0100 Subject: [PATCH 08/20] Update: Implemenation --- NodeTypes/Content/Video.yaml | 1 - NodeTypes/Mixin/VideoID.yaml | 8 +- Resources/Private/Fusion/Content.Video.fusion | 217 ++++++++++++++++++ .../Private/Fusion/ReplaceIframes.fusion | 6 +- Resources/Private/Fusion/Root.fusion | 2 +- Resources/Private/Translations/de/Main.xlf | 20 -- Resources/Private/Translations/en/Main.xlf | 20 -- Resources/Private/Translations/fr/Main.xlf | 20 -- 8 files changed, 221 insertions(+), 73 deletions(-) create mode 100644 Resources/Private/Fusion/Content.Video.fusion delete mode 100644 Resources/Private/Translations/de/Main.xlf delete mode 100644 Resources/Private/Translations/en/Main.xlf delete mode 100644 Resources/Private/Translations/fr/Main.xlf diff --git a/NodeTypes/Content/Video.yaml b/NodeTypes/Content/Video.yaml index c8ee2fd..52807bd 100644 --- a/NodeTypes/Content/Video.yaml +++ b/NodeTypes/Content/Video.yaml @@ -10,7 +10,6 @@ # If you want to give the editor more control, # you can also add also these mixins: - # 'Jonnitto.PrettyEmbedHelper:Mixin.AllowFullScreen': true # 'Jonnitto.PrettyEmbedHelper:Mixin.Loop': true # 'Jonnitto.PrettyEmbedHelper:Mixin.Controls': true ui: diff --git a/NodeTypes/Mixin/VideoID.yaml b/NodeTypes/Mixin/VideoID.yaml index b83cf61..032062a 100644 --- a/NodeTypes/Mixin/VideoID.yaml +++ b/NodeTypes/Mixin/VideoID.yaml @@ -1,13 +1,7 @@ 'Jonnitto.PrettyEmbedVideoPlatforms:Mixin.VideoID': abstract: true superTypes: - 'Jonnitto.PrettyEmbedHelper:Mixin.Force16to9': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.ID': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.Title': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.Ratio': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.Image': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.Thumbnail': true - 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata.Duration': true + 'Jonnitto.PrettyEmbedHelper:Mixin.Metadata': true properties: platform: type: string diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion new file mode 100644 index 0000000..af065f5 --- /dev/null +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -0,0 +1,217 @@ +prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto.PrettyEmbed:Content) { + @propTypes { + // These properties are already defined in Jonnitto.PrettyEmbed:Content + maximumWidth = ${PropTypes.integer} + loadImageStrategy = ${PropTypes.oneOf(['lazy', 'eager', null, false])} + wrapper = ${PropTypes.anyOf(PropTypes.string, PropTypes.boolean)} + image = ${PropTypes.instanceOf('Neos\Media\Domain\Model\ImageInterface')} + metadata = ${PropTypes.shape({ + 'videoID': PropTypes.anyOf(PropTypes.string, PropTypes.integer), + 'title': PropTypes.string, + 'aspectRatio': PropTypes.anyOf(PropTypes.string, PropTypes.integer, PropTypes.float), + 'duration': PropTypes.integer, + 'image': PropTypes.string, + 'thumbnail': PropTypes.instanceOf('Neos\Media\Domain\Model\ImageInterface'), + 'href': PropTypes.string, + 'embedHref': PropTypes.string + })} + + // Use this for a custom poster src set + posterSrcset = ${PropTypes.string} + } + + label = ${this.metadata ? this.metadata.title : null} + aspectRatio = ${this.metadata ? this.metadata.aspectRatio : null} + + platform = ${q(node).property('platform')} + player = ${this.platform == 'youtube' ? 'YouTube' : 'Vimeo'} + type = ${q(node).property('type')} + videoID = ${q(node).property('videoID')} + async = true + + // This can used as alternative preview + content = null + + showBackendNotification = true + + // `false` to disable the gdpr message, `popup` to open the video in a new window or `true` to show the gdpr message in the player + gdprHandling = Jonnitto.PrettyEmbed:GetProperty { + property = 'gdprHandling' + } + + // Should the video be opened on a lightbox? + lightbox = Jonnitto.PrettyEmbed:GetProperty { + property = 'lightbox' + } + + // When the lightbox is set, should the preview image preserve his aspect ratio? + preserveAspectRatio = Jonnitto.PrettyEmbed:GetProperty { + property = 'preserveAspectRatio' + } + + // If no aspect ratio can be calcualted from the oembed service, you have the possibility to set a fallback aspect ratio. + fallbackAspectRatio = Jonnitto.PrettyEmbed:GetProperty { + property = 'fallbackAspectRatio' + } + + // Whether to restart the video automatically after reaching the end. + loop = Jonnitto.PrettyEmbed:GetProperty { + property = 'loop' + } + + // This parameter indicates whether the video player controls are displayed + controls = Jonnitto.PrettyEmbed:GetProperty { + property = 'controls' + } + + + //////////////////////////////// + // Additional settings for Vimeo + //////////////////////////////// + + // Whether the player is in background mode, which hides the playback controls, enables autoplay, and loops the video. + background = Jonnitto.PrettyEmbed:GetProperty { + property = 'background' + } + + // The hexadecimal color value of the playback controls, which is normally 00ADEF. + color = Jonnitto.PrettyEmbed:GetProperty { + property = 'color' + } + + // Internal + videoID.@process.getIDFromUrl = ${this.metadata.videoID ? this.metadata.videoID : (value && this.platform ? Jonnitto.PrettyEmbedHelper.platformID(value, this.platform) : value)} + + renderer = Neos.Fusion:Component { + @apply.props = ${props} + preview = ${props.content || null} + + href = Neos.Fusion:Case { + hasHref { + condition = ${props.metadata.href} + renderer = ${props.metadata.href} + } + vimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, false)} + } + youtube { + condition = ${props.videoID && props.platform == 'youtube'} + renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, false)} + } + } + + embedHref = Neos.Fusion:Case { + hasHref { + condition = ${props.metadata.embedHref} + renderer = ${props.metadata.embedHref} + } + vimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, true)} + } + youtube { + condition = ${props.videoID && props.platform == 'youtube'} + renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, true)} + } + } + + poster = Neos.Fusion:Case { + @if.noCustomPreview = ${!props.content} + hasPersistentResource { + condition = ${props.image || props.metadata.thumbnail} + renderer = Neos.Neos:ImageUri { + asset = ${props.image || props.metadata.thumbnail} + async = ${props.async} + maximumWidth = ${props.maximumWidth} + } + } + imageFromVimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.vimeoThumbnail(props.videoID)} + } + imageFromYouTube { + condition = ${props.videoID && props.platform == 'youtube' && props.type == 'video'} + renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.youtubeThumbnail(props.videoID)} + } + } + poster2x = Neos.Neos:ImageUri { + @if { + noCustomSrcSet = ${!props.posterSrcset} + noCustomPreview = ${!props.content} + hasAsset = ${props.image || props.metadata.thumbnail} + hasEnoughPixel = ${props.image ? props.image.width >= props.maximumWidth * 2 : props.metadata.thumbnail.width >= props.maximumWidth * 2} + } + asset = ${props.image || props.metadata.thumbnail} + async = ${props.async} + maximumWidth = ${props.maximumWidth * 2} + } + + renderer = Neos.Fusion:Case { + noVideoID { + condition = ${!props.videoID || !props.platform} + renderer = Jonnitto.PrettyEmbed:Notification { + @if.set = ${props.showBackendNotification} + key = 'noVideoID' + default = 'Please add a Video URL / ID or url in the inspector' + } + } + noPosterOrPreview { + condition = ${!props.poster && !props.preview} + renderer = Jonnitto.PrettyEmbed:Notification { + @if.set = ${props.showBackendNotification} + key = 'needPreviewImage' + default = 'You need to define a custom preview image.' + } + } + youtube { + condition = ${props.platform == 'youtube'} + renderer = Jonnitto.PrettyEmbed:Presentation.YouTube { + maximumWidth = ${props.maximumWidth} + loadImageStrategy = ${props.loadImageStrategy} + wrapper = ${props.wrapper} + gdprHandling = ${props.gdprHandling} + controls = ${props.controls} + loop = ${props.loop} + lightbox = ${props.lightbox} + preserveAspectRatio = ${props.preserveAspectRatio} + fallbackAspectRatio = ${props.fallbackAspectRatio} + label = ${props.label} + aspectRatio = ${props.aspectRatio} + preview = ${props.preview} + poster = ${props.poster} + poster2x = ${props.poster2x} + posterSrcset = ${props.posterSrcset} + videoId = ${props.type == 'video' ? props.videoID : null} + playlistId = ${props.type == 'playlist' ? props.videoID : null} + href = ${props.href} + embedHref = ${props.embedHref} + } + } + vimeo { + condition = ${props.platform == 'vimeo'} + renderer = Jonnitto.PrettyEmbed:Presentation.Vimeo { + maximumWidth = ${props.maximumWidth} + loadImageStrategy = ${props.loadImageStrategy} + wrapper = ${props.wrapper} + gdprHandling = ${props.gdprHandling} + controls = ${props.controls} + loop = ${props.loop} + lightbox = ${props.lightbox} + preserveAspectRatio = ${props.preserveAspectRatio} + fallbackAspectRatio = ${props.fallbackAspectRatio} + label = ${props.label} + aspectRatio = ${props.aspectRatio} + preview = ${props.preview} + poster = ${props.poster} + poster2x = ${props.poster2x} + posterSrcset = ${props.posterSrcset} + videoId = ${props.videoID} + color = ${props.color} + href = ${props.href} + embedHref = ${props.embedHref} + } + } + } + } +} diff --git a/Resources/Private/Fusion/ReplaceIframes.fusion b/Resources/Private/Fusion/ReplaceIframes.fusion index 47effaa..552f163 100644 --- a/Resources/Private/Fusion/ReplaceIframes.fusion +++ b/Resources/Private/Fusion/ReplaceIframes.fusion @@ -6,10 +6,9 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { // This property is used internally by `ReplaceIframesImplementation` to render each YouTube iframe. // It can be modified to change behaviour for all rendered YouTube items. - itemYoutubeRenderer = Jonnitto.PrettyEmbedVideoPlatforms:Component.Video { + itemYoutubeRenderer = Jonnitto.PrettyEmbed:Presentation.YouTube { type = ${type} videoID = ${videoID} - platform = 'youtube' poster = ${poster} // Set this to replace the preview image @@ -18,10 +17,9 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { // This property is used internally by `ReplaceIframesImplementation` to render each Vimeo iframe. // It can be modified to change behaviour for all rendered Vimeo items. - itemVimeoRenderer = Jonnitto.PrettyEmbedVideoPlatforms:Component.Video { + itemVimeoRenderer = Jonnitto.PrettyEmbed:Presentation.Vimeo { videoID = ${videoID} type = 'video' - platform = 'vimeo' poster = ${poster} // Set this to replace the preview image diff --git a/Resources/Private/Fusion/Root.fusion b/Resources/Private/Fusion/Root.fusion index fe1d560..56095c3 100644 --- a/Resources/Private/Fusion/Root.fusion +++ b/Resources/Private/Fusion/Root.fusion @@ -1 +1 @@ -include: **/*.fusion +include: *.fusion diff --git a/Resources/Private/Translations/de/Main.xlf b/Resources/Private/Translations/de/Main.xlf deleted file mode 100644 index e16142c..0000000 --- a/Resources/Private/Translations/de/Main.xlf +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - You need to define a custom preview image. - Es muss ein Vorschaubild angegeben werden. - - - Please add a video URL or ID in the inspector - Bitte Video URL oder ID im Inspektor hinzufügen - - - en - de - - - - diff --git a/Resources/Private/Translations/en/Main.xlf b/Resources/Private/Translations/en/Main.xlf deleted file mode 100644 index 2bab6cc..0000000 --- a/Resources/Private/Translations/en/Main.xlf +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - You need to define a custom preview image. - You need to define a custom preview image. - - - Please add a video URL or ID in the inspector - Please add a video URL or ID in the inspector - - - en - en - - - - diff --git a/Resources/Private/Translations/fr/Main.xlf b/Resources/Private/Translations/fr/Main.xlf deleted file mode 100644 index 6a875b9..0000000 --- a/Resources/Private/Translations/fr/Main.xlf +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - You need to define a custom preview image. - Vous devez définir une image de prévisualisation personnalisée. - - - Please add a video URL or ID in the inspector - Veuillez ajouter l'URL ou l'ID de la vidéo dans l'inspecteur - - - en - fr - - - - From 4a9050c3df41e8af08ab020ae65e325c7ff4c3ba Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sat, 9 Dec 2023 23:34:09 +0100 Subject: [PATCH 09/20] Update: Debug output --- Resources/Private/Fusion/Content.Video.fusion | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion index af065f5..0ae8c15 100644 --- a/Resources/Private/Fusion/Content.Video.fusion +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -148,6 +148,10 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto } renderer = Neos.Fusion:Case { + @process.debug = Neos.Fusion:Debug.Console { + @if.debug = ${props._debug} + props = ${props} + } noVideoID { condition = ${!props.videoID || !props.platform} renderer = Jonnitto.PrettyEmbed:Notification { From d984ede29bf33a32fc4567c61fa76dc28baaff6c Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sun, 10 Dec 2023 01:10:47 +0100 Subject: [PATCH 10/20] Fix: embedhref and mixed up variables --- .../FusionObjects/ReplaceIframesImplementation.php | 14 +++++++++++--- Resources/Private/Fusion/Content.Video.fusion | 6 +++--- Resources/Private/Fusion/ReplaceIframes.fusion | 6 +++++- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/Classes/FusionObjects/ReplaceIframesImplementation.php b/Classes/FusionObjects/ReplaceIframesImplementation.php index cbf91c4..d1068d8 100644 --- a/Classes/FusionObjects/ReplaceIframesImplementation.php +++ b/Classes/FusionObjects/ReplaceIframesImplementation.php @@ -82,25 +82,33 @@ public function evaluate(): string protected function buildYoutube(string $videoID, string $type): string { $poster = Utility::youtubeThumbnail($videoID); + $href = Utility::youtubeHref($videoID, $type, false); + $embedHref = Utility::youtubeHref($videoID, $type, true); $this->runtime->pushContextArray([ 'videoID' => $videoID, 'type' => $type, 'poster' => $poster, + 'href' => $href, + 'embedHref' => $embedHref, ]); $html = $this->runtime->render($this->path . '/itemYoutubeRenderer'); $this->runtime->popContext(); - return $html; + return $html ?? ''; } protected function buildVimeo(string $videoID): string { $poster = Utility::vimeoThumbnail($videoID); + $href = Utility::vimeoHref($videoID, false); + $embedHref = Utility::vimeoHref($videoID, true); $this->runtime->pushContextArray([ 'videoID' => $videoID, - 'poster' => $poster + 'poster' => $poster, + 'href' => $href, + 'embedHref' => $embedHref, ]); $html = $this->runtime->render($this->path . '/itemVimeoRenderer'); $this->runtime->popContext(); - return $html; + return $html ?? ''; } } diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion index 0ae8c15..94c0d62 100644 --- a/Resources/Private/Fusion/Content.Video.fusion +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -186,8 +186,8 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto poster = ${props.poster} poster2x = ${props.poster2x} posterSrcset = ${props.posterSrcset} - videoId = ${props.type == 'video' ? props.videoID : null} - playlistId = ${props.type == 'playlist' ? props.videoID : null} + videoID = ${props.type == 'video' ? props.videoID : null} + playlistID = ${props.type == 'playlist' ? props.videoID : null} href = ${props.href} embedHref = ${props.embedHref} } @@ -210,7 +210,7 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto poster = ${props.poster} poster2x = ${props.poster2x} posterSrcset = ${props.posterSrcset} - videoId = ${props.videoID} + videoID = ${props.videoID} color = ${props.color} href = ${props.href} embedHref = ${props.embedHref} diff --git a/Resources/Private/Fusion/ReplaceIframes.fusion b/Resources/Private/Fusion/ReplaceIframes.fusion index 552f163..c753479 100644 --- a/Resources/Private/Fusion/ReplaceIframes.fusion +++ b/Resources/Private/Fusion/ReplaceIframes.fusion @@ -10,17 +10,21 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { type = ${type} videoID = ${videoID} poster = ${poster} + href = ${href} + embedHref = ${embedHref} // Set this to replace the preview image content = null + gdprHandling = false } // This property is used internally by `ReplaceIframesImplementation` to render each Vimeo iframe. // It can be modified to change behaviour for all rendered Vimeo items. itemVimeoRenderer = Jonnitto.PrettyEmbed:Presentation.Vimeo { videoID = ${videoID} - type = 'video' poster = ${poster} + href = ${href} + embedHref = ${embedHref} // Set this to replace the preview image content = null From 14f90bcf803295112bbfca624b45260f7d6c6f9e Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Sun, 10 Dec 2023 01:11:47 +0100 Subject: [PATCH 11/20] Fix: Remove gdpr handling value --- Resources/Private/Fusion/ReplaceIframes.fusion | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Private/Fusion/ReplaceIframes.fusion b/Resources/Private/Fusion/ReplaceIframes.fusion index c753479..8ac900f 100644 --- a/Resources/Private/Fusion/ReplaceIframes.fusion +++ b/Resources/Private/Fusion/ReplaceIframes.fusion @@ -15,7 +15,6 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { // Set this to replace the preview image content = null - gdprHandling = false } // This property is used internally by `ReplaceIframesImplementation` to render each Vimeo iframe. From ebaba5105f014fb43e64e72ca7d547e9f566b3c3 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 18:32:46 +0100 Subject: [PATCH 12/20] Update: Add .gitignore to not exported files --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index ef1581d..818b09f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ /.gitattributes export-ignore /.github export-ignore +/.gitignore export-ignore /CODE_OF_CONDUCT.md export-ignore From a90a3aa6dede93439dc9a90163e22955dd3d159f Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 18:33:42 +0100 Subject: [PATCH 13/20] Breaking: Remove ReplaceIframes Fusion. This is now in the helper package --- .../ReplaceIframesImplementation.php | 114 ------------------ .../Private/Fusion/ReplaceIframes.fusion | 31 ----- 2 files changed, 145 deletions(-) delete mode 100644 Classes/FusionObjects/ReplaceIframesImplementation.php delete mode 100644 Resources/Private/Fusion/ReplaceIframes.fusion diff --git a/Classes/FusionObjects/ReplaceIframesImplementation.php b/Classes/FusionObjects/ReplaceIframesImplementation.php deleted file mode 100644 index d1068d8..0000000 --- a/Classes/FusionObjects/ReplaceIframesImplementation.php +++ /dev/null @@ -1,114 +0,0 @@ -fusionValue('content'); - } - - /** - * Render Replace embeded iframes with the pretty embeded markup - * - * @return string - */ - public function evaluate(): string - { - $content = $this->getContent(); - - if (!strpos($content, ']*?src=\"(https:\/\/www\.youtube(?:-nocookie)?\.com\/embed\/[^"]*)(?:(?!<\/iframe>).)+<\/iframe>/im', $content, $youtubeIframeMatcher, PREG_SET_ORDER); - preg_match_all('/]*?src=\"(https:\/\/player\.vimeo\.com\/video\/[^"]*)(?:(?!<\/iframe>).)+<\/iframe>/im', $content, $vimeoIframeMatcher, PREG_SET_ORDER); - $parseID = new ParseIDService(); - - foreach ($youtubeIframeMatcher as $array) { - $iframe = $array[0] ?? null; - $url = $array[1] ?? null; - if (!$iframe || !$url) { - continue; - } - $videoID = $parseID->youtube($url); - if (!$videoID) { - continue; - } - $type = $this->youtubeService->type($url); - $replacement = $this->buildYoutube($videoID, $type); - $content = str_replace($iframe, $replacement, $content); - } - - foreach ($vimeoIframeMatcher as $array) { - $iframe = $array[0] ?? null; - $url = $array[1] ?? null; - if (!$iframe || !$url) { - continue; - } - $videoID = $parseID->vimeo($url); - if (!$videoID) { - continue; - } - $replacement = $this->buildVimeo($videoID); - $content = str_replace($iframe, $replacement, $content); - } - - return $content; - } - - protected function buildYoutube(string $videoID, string $type): string - { - $poster = Utility::youtubeThumbnail($videoID); - $href = Utility::youtubeHref($videoID, $type, false); - $embedHref = Utility::youtubeHref($videoID, $type, true); - $this->runtime->pushContextArray([ - 'videoID' => $videoID, - 'type' => $type, - 'poster' => $poster, - 'href' => $href, - 'embedHref' => $embedHref, - ]); - $html = $this->runtime->render($this->path . '/itemYoutubeRenderer'); - $this->runtime->popContext(); - return $html ?? ''; - } - - protected function buildVimeo(string $videoID): string - { - $poster = Utility::vimeoThumbnail($videoID); - $href = Utility::vimeoHref($videoID, false); - $embedHref = Utility::vimeoHref($videoID, true); - $this->runtime->pushContextArray([ - 'videoID' => $videoID, - 'poster' => $poster, - 'href' => $href, - 'embedHref' => $embedHref, - ]); - $html = $this->runtime->render($this->path . '/itemVimeoRenderer'); - $this->runtime->popContext(); - return $html ?? ''; - } -} diff --git a/Resources/Private/Fusion/ReplaceIframes.fusion b/Resources/Private/Fusion/ReplaceIframes.fusion deleted file mode 100644 index 8ac900f..0000000 --- a/Resources/Private/Fusion/ReplaceIframes.fusion +++ /dev/null @@ -1,31 +0,0 @@ -prototype(Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes) { - @class = 'Jonnitto\\PrettyEmbedVideoPlatforms\\FusionObjects\\ReplaceIframesImplementation' - - // The content to parse - content = ${value} - - // This property is used internally by `ReplaceIframesImplementation` to render each YouTube iframe. - // It can be modified to change behaviour for all rendered YouTube items. - itemYoutubeRenderer = Jonnitto.PrettyEmbed:Presentation.YouTube { - type = ${type} - videoID = ${videoID} - poster = ${poster} - href = ${href} - embedHref = ${embedHref} - - // Set this to replace the preview image - content = null - } - - // This property is used internally by `ReplaceIframesImplementation` to render each Vimeo iframe. - // It can be modified to change behaviour for all rendered Vimeo items. - itemVimeoRenderer = Jonnitto.PrettyEmbed:Presentation.Vimeo { - videoID = ${videoID} - poster = ${poster} - href = ${href} - embedHref = ${embedHref} - - // Set this to replace the preview image - content = null - } -} From 080c2b66b41e72af82eb9dcc037d66af9b72ca90 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 18:33:59 +0100 Subject: [PATCH 14/20] Chore: Code cleanup --- Resources/Private/Fusion/Content.Video.fusion | 166 ++++++++---------- 1 file changed, 75 insertions(+), 91 deletions(-) diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion index 94c0d62..9fd7a7f 100644 --- a/Resources/Private/Fusion/Content.Video.fusion +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -1,10 +1,13 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto.PrettyEmbed:Content) { @propTypes { // These properties are already defined in Jonnitto.PrettyEmbed:Content + id = ${PropTypes.string} + class = ${PropTypes.anyOf( PropTypes.string, PropTypes.arrayOf( PropTypes.string ) )} maximumWidth = ${PropTypes.integer} loadImageStrategy = ${PropTypes.oneOf(['lazy', 'eager', null, false])} wrapper = ${PropTypes.anyOf(PropTypes.string, PropTypes.boolean)} image = ${PropTypes.instanceOf('Neos\Media\Domain\Model\ImageInterface')} + async = ${PropTypes.boolean} metadata = ${PropTypes.shape({ 'videoID': PropTypes.anyOf(PropTypes.string, PropTypes.integer), 'title': PropTypes.string, @@ -27,7 +30,6 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto player = ${this.platform == 'youtube' ? 'YouTube' : 'Vimeo'} type = ${q(node).property('type')} videoID = ${q(node).property('videoID')} - async = true // This can used as alternative preview content = null @@ -84,67 +86,81 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto renderer = Neos.Fusion:Component { @apply.props = ${props} - preview = ${props.content || null} - href = Neos.Fusion:Case { - hasHref { - condition = ${props.metadata.href} - renderer = ${props.metadata.href} - } - vimeo { - condition = ${props.videoID && props.platform == 'vimeo'} - renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, false)} - } - youtube { - condition = ${props.videoID && props.platform == 'youtube'} - renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, false)} - } - } - - embedHref = Neos.Fusion:Case { - hasHref { - condition = ${props.metadata.embedHref} - renderer = ${props.metadata.embedHref} - } - vimeo { - condition = ${props.videoID && props.platform == 'vimeo'} - renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, true)} - } - youtube { - condition = ${props.videoID && props.platform == 'youtube'} - renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, true)} - } - } - - poster = Neos.Fusion:Case { - @if.noCustomPreview = ${!props.content} - hasPersistentResource { - condition = ${props.image || props.metadata.thumbnail} - renderer = Neos.Neos:ImageUri { - asset = ${props.image || props.metadata.thumbnail} - async = ${props.async} - maximumWidth = ${props.maximumWidth} + _basisOptions = Neos.Fusion:DataStructure { + id = ${props.id} + class = ${props.class} + maximumWidth = ${props.maximumWidth} + loadImageStrategy = ${props.loadImageStrategy} + wrapper = ${props.wrapper} + gdprHandling = ${props.gdprHandling} + controls = ${props.controls} + loop = ${props.loop} + lightbox = ${props.lightbox} + preserveAspectRatio = ${props.preserveAspectRatio} + fallbackAspectRatio = ${props.fallbackAspectRatio} + label = ${props.label} + aspectRatio = ${props.aspectRatio} + preview = ${props.content || null} + posterSrcset = ${props.posterSrcset} + poster = Neos.Fusion:Case { + @if.noCustomPreview = ${!props.content} + hasPersistentResource { + condition = ${props.image || props.metadata.thumbnail} + renderer = Neos.Neos:ImageUri { + asset = ${props.image || props.metadata.thumbnail} + async = ${props.async} + maximumWidth = ${props.maximumWidth} + } + } + imageFromVimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.vimeoThumbnail(props.videoID)} + } + imageFromYouTube { + condition = ${props.videoID && props.platform == 'youtube' && props.type == 'video'} + renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.youtubeThumbnail(props.videoID)} } } - imageFromVimeo { - condition = ${props.videoID && props.platform == 'vimeo'} - renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.vimeoThumbnail(props.videoID)} + poster2x = Neos.Neos:ImageUri { + @if { + noCustomSrcSet = ${!props.posterSrcset} + noCustomPreview = ${!props.content} + hasAsset = ${props.image || props.metadata.thumbnail} + hasEnoughPixel = ${props.image ? props.image.width >= props.maximumWidth * 2 : props.metadata.thumbnail.width >= props.maximumWidth * 2} + } + asset = ${props.image || props.metadata.thumbnail} + async = ${props.async} + maximumWidth = ${props.maximumWidth * 2} } - imageFromYouTube { - condition = ${props.videoID && props.platform == 'youtube' && props.type == 'video'} - renderer = ${props.metadata.image || Jonnitto.PrettyEmbedHelper.youtubeThumbnail(props.videoID)} + href = Neos.Fusion:Case { + hasHref { + condition = ${props.metadata.href} + renderer = ${props.metadata.href} + } + vimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, false)} + } + youtube { + condition = ${props.videoID && props.platform == 'youtube'} + renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, false)} + } } - } - poster2x = Neos.Neos:ImageUri { - @if { - noCustomSrcSet = ${!props.posterSrcset} - noCustomPreview = ${!props.content} - hasAsset = ${props.image || props.metadata.thumbnail} - hasEnoughPixel = ${props.image ? props.image.width >= props.maximumWidth * 2 : props.metadata.thumbnail.width >= props.maximumWidth * 2} + embedHref = Neos.Fusion:Case { + hasHref { + condition = ${props.metadata.embedHref} + renderer = ${props.metadata.embedHref} + } + vimeo { + condition = ${props.videoID && props.platform == 'vimeo'} + renderer = ${Jonnitto.PrettyEmbedHelper.vimeoHref(props.videoID, true)} + } + youtube { + condition = ${props.videoID && props.platform == 'youtube'} + renderer = ${Jonnitto.PrettyEmbedHelper.youtubeHref(props.videoID, props.type, true)} + } } - asset = ${props.image || props.metadata.thumbnail} - async = ${props.async} - maximumWidth = ${props.maximumWidth * 2} } renderer = Neos.Fusion:Case { @@ -161,7 +177,7 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto } } noPosterOrPreview { - condition = ${!props.poster && !props.preview} + condition = ${!props._basisOptions.poster && !props._basisOptions.preview} renderer = Jonnitto.PrettyEmbed:Notification { @if.set = ${props.showBackendNotification} key = 'needPreviewImage' @@ -171,49 +187,17 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto youtube { condition = ${props.platform == 'youtube'} renderer = Jonnitto.PrettyEmbed:Presentation.YouTube { - maximumWidth = ${props.maximumWidth} - loadImageStrategy = ${props.loadImageStrategy} - wrapper = ${props.wrapper} - gdprHandling = ${props.gdprHandling} - controls = ${props.controls} - loop = ${props.loop} - lightbox = ${props.lightbox} - preserveAspectRatio = ${props.preserveAspectRatio} - fallbackAspectRatio = ${props.fallbackAspectRatio} - label = ${props.label} - aspectRatio = ${props.aspectRatio} - preview = ${props.preview} - poster = ${props.poster} - poster2x = ${props.poster2x} - posterSrcset = ${props.posterSrcset} + @apply.props = ${props._basisOptions} videoID = ${props.type == 'video' ? props.videoID : null} playlistID = ${props.type == 'playlist' ? props.videoID : null} - href = ${props.href} - embedHref = ${props.embedHref} } } vimeo { condition = ${props.platform == 'vimeo'} renderer = Jonnitto.PrettyEmbed:Presentation.Vimeo { - maximumWidth = ${props.maximumWidth} - loadImageStrategy = ${props.loadImageStrategy} - wrapper = ${props.wrapper} - gdprHandling = ${props.gdprHandling} - controls = ${props.controls} - loop = ${props.loop} - lightbox = ${props.lightbox} - preserveAspectRatio = ${props.preserveAspectRatio} - fallbackAspectRatio = ${props.fallbackAspectRatio} - label = ${props.label} - aspectRatio = ${props.aspectRatio} - preview = ${props.preview} - poster = ${props.poster} - poster2x = ${props.poster2x} - posterSrcset = ${props.posterSrcset} + @apply.props = ${props._basisOptions} videoID = ${props.videoID} color = ${props.color} - href = ${props.href} - embedHref = ${props.embedHref} } } } From ef744353fa3ee7ff144efd661ca9cc39a69138a6 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 18:48:29 +0100 Subject: [PATCH 15/20] Update: Readme and code of conduct --- CODE_OF_CONDUCT.md | 46 ++++++++++++++++ README.md | 134 ++++++++++++++++----------------------------- 2 files changed, 94 insertions(+), 86 deletions(-) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..31b16fa --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@uhlmann.pro. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/README.md b/README.md index 78aa1f7..e495689 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,19 @@ # Jonnitto.PrettyEmbedVideoPlatforms -Prettier embeds for your Vimeo videos and YouTube videos/playlists in [Neos CMS] - with helpful options like high-res preview images, lightbox feature, and advanced customization of embed options. +Prettier embeds for your Vimeo videos and YouTube videos/playlists in [Neos CMS] - with helpful options like high-res +preview images, lightbox feature, and advanced customization of embed options. + +![Screenshot] | Version | Neos | Maintained | | ------- | ----------- | :--------: | -| 1.\* | 4.2.\*, > 5 | ✗ | -| 2.\* | >= 5.3 | ✗ | -| 3.\* | >= 5.3 | ✗ | -| 4.\* | >= 7.3 | ✓ | +| 1.\* | 4.2.\*, > 5 | ✗ | +| 2.\* | >= 5.3 | ✗ | +| 3.\* | >= 5.3 | ✗ | +| 6.\* | >= 7.3 | ✓ | + +> The version jump was made to have all packages from the PrettyEmbed series on the same number ## Installation @@ -45,7 +50,7 @@ All packages from the PrettyEmbed series have the benefit of a better frontend p ### Global settings for the whole PrettyEmbed series -The settings will be set globally from the [PrettyEmbedHelper] package. These are the default settings: +The settings will be set globally from the [PrettyEmbedHelper] package. These are the default settings for this package: ```yaml Jonnitto: @@ -53,7 +58,7 @@ Jonnitto: # If you have your own AlpineJS in your setup, you can disable the check here. Alpine must be an global variable includeAlpineJsCheck: true - # If you want to use your own assets, set this to false (Backend.Video.css ignores this setting) + # If you want to use your own assets, set this to false includeAssets: css: true js: true @@ -69,8 +74,8 @@ Jonnitto: # The buttons which get injected (file content) to the player. # You can also overwrite the button Fusion components button: - play: 'resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PlayButton.svg' - pause: 'resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PauseButton.svg' + play: "resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PlayButton.svg" + pause: "resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PauseButton.svg" # This is the maximum width of a custom preview image maximumWidth: 1920 @@ -98,8 +103,8 @@ Jonnitto: # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties preserveAspectRatio: true - # If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9. Per default this is set via the node properties - force16to9: true + # If no aspect ratio can be calcualted from the oembed service, you have the possibility to set a fallback aspect ratio. + fallbackAspectRatio: "16 / 9" YouTube: # Set to false to disable the gdpr message, set to popup open the video in a new window or set to true to show the message in the player @@ -123,60 +128,8 @@ Jonnitto: # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties preserveAspectRatio: true - # If no aspect ratio can be calcualted from the oembed service, you have the possibility to force the aspect ratio 16:9. Per default this is set via the node properties - force16to9: true - - Video: - # If true, the browser will offer controls to allow the user to control - # video playback, including volume, seeking, and pause/resume playback. - controls: true - - # Should the video be opened on a lightbox? Per default this is set via the node properties - lightbox: false - - # If true, the video automatically begins to play back as soon - # as it can do so without stopping to finish loading the data. - autoplay: false - - # If true, the browser will automatically seek back - # to the start upon reaching the end of the video. - loop: false - - # Whether the video is muted upon loading. Set automatically to true if autoplay is enabled - muted: false - - # This enumerated attribute is intended to provide a hint to the browser about what - # the author thinks will lead to the best user experience with regards to what content - # is loaded before the video is played. It may have one of the following values: - # - none Indicates that the video should not be preloaded. - # - metadata Indicates that only video metadata (e.g. length) is fetched. - # - auto Indicates that the whole video file can be downloaded, even if the user is not expected to use it - preload: none - - # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attr-crossorigin - # anonymous || use-credentials || true || false - crossorigin: false - - Audio: - # If true, the browser will offer controls to allow the user to control - # audio playback, including volume, seeking, and pause/resume playback. - controls: true - - # If true, the browser will automatically seek back - # to the start upon reaching the end of the audio. - loop: false - - # This enumerated attribute is intended to provide a hint to the browser about what - # the author thinks will lead to the best user experience with regards to what content - # is loaded before the audio is played. It may have one of the following values: - # - none Indicates that the audio should not be preloaded. - # - metadata Indicates that the browser should load only metadata when the page loads - # - auto Indicates that the whole audio file can be downloaded, even if the user is not expected to use it - preload: metadata - - # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio#attr-crossorigin - # anonymous || use-credentials || true || false - crossorigin: false + # If no aspect ratio can be calcualted from the oembed service, you have the possibility to set a fallback aspect ratio. + fallbackAspectRatio: "16 / 9" ``` #### Disable inclusion of the CSS and/or JS files @@ -206,8 +159,12 @@ If you use SCCS in your build pipeline, you can adjust the look and feel of [`Ma ```scss // Buttons (play / pause) $prettyembed-button-play-size: 72px !default; -$prettyembed-button-pause-size: calc($prettyembed-button-play-size / 2) !default; -$prettyembed-button-pause-margin: calc($prettyembed-button-pause-size / 2) !default; +$prettyembed-button-pause-size: calc( + $prettyembed-button-play-size / 2 +) !default; +$prettyembed-button-pause-margin: calc( + $prettyembed-button-pause-size / 2 +) !default; $prettyembed-button-opacity: 0.9 !default; $prettyembed-button-scale: 0.8 !default; $prettyembed-button-scale-hover: 1 !default; @@ -274,38 +231,44 @@ choose if the video is has the controls from the platform, you can activate the node types like that: ```yaml -'Jonnitto.PrettyEmbedVideoPlatforms:Content.Video': +"Jonnitto.PrettyEmbedVideoPlatforms:Content.Video": superTypes: - 'Jonnitto.PrettyEmbedHelper:Mixin.Controls': true + "Jonnitto.PrettyEmbedHelper:Mixin.Controls": true ``` These are the available mixins: -| Mixin name (Prefix: `Jonnitto.PrettyEmbed`) | Description | Default value | Enabled per default | -| -------------------------------------------------------- | --------------------------------------------------------------------------- | :-----------: | :-----------------: | -| `Helper:Mixin.Groups` | Enables the inspector groups | | ✓ | -| `Helper:Mixin.Image` | Add the preview image property | | ✓ | -| `Helper:Mixin.Lightbox` | Open the video in a lightbox | `false` | ✓ | -| `Helper:Mixin.PreserveAspectRatio` | If the lightbox is active, the preview image can preserve his aspect ratio. | `true` | ✓ | -| `Helper:Mixin.BackendLabel` | Read the title of the video and set this as label in the content tree | | ✓ | -| `VideoPlatforms:Mixin.VideoID` | Let the user enter the video ID or the URL | | ✓ | -| `Helper:Mixin.AllowFullScreen` | Allow fullscreen or not | `true` | | -| `Helper:Mixin.Loop` | Loop the video | `false` | | -| `Helper:Mixin.Controls` | Show the controls | `true` | | +| Mixin name (Prefix: `Jonnitto.PrettyEmbed`) | Description | Default value | Enabled per default | +| ------------------------------------------- | --------------------------------------------------------------------------- | :-----------: | :-----------------: | +| `Helper:Mixin.Groups` | Enables the inspector groups | | ✓ | +| `Helper:Mixin.Image` | Add the preview image property | | ✓ | +| `Helper:Mixin.Lightbox` | Open the video in a lightbox | `false` | ✓ | +| `Helper:Mixin.PreserveAspectRatio` | If the lightbox is active, the preview image can preserve his aspect ratio. | `true` | ✓ | +| `Helper:Mixin.BackendLabel` | Read the title of the video and set this as label in the content tree | | ✓ | +| `VideoPlatforms:Mixin.VideoID` | Let the user enter the video ID or the URL | | ✓ | +| `Helper:Mixin.Loop` | Loop the video | `false` | | +| `Helper:Mixin.Controls` | Show the controls | `true` | | If you want to include the video in your node type, you should use at least the mixin `Jonnitto.PrettyEmbedVideoPlatforms:Mixin.VideoID`. This add besides the `videoID` property also the properties for the metadata fetched from the oembed service. This mixin is also necessary to fetch/update the data from the service. ### Fusion -If you want to use the player as a pure component, you can use the [`Jonnitto.PrettyEmbedVideoPlatforms:Component.Video`] fusion prototype. +If you want to use the player as a pure component, you can use the `Jonnitto.PrettyEmbed:Presentation.YouTube` or +`Jonnitto.PrettyEmbed:Presentation.Vimeo` Fusion prototype. If you want to read the node properties and let the package handle all for you, you should use the [`Jonnitto.PrettyEmbedVideoPlatforms:Content.Video`] prototype. For more comfortable including in your node types, you can disable the content element wrapping with `contentElement = false`. This is useful if you want to create, for example, a text with a video node type. -If you want to parse existing content with iframes and replace them automatically, you can add [`Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes`] with an `@process` like that: `@process.replaceIframes = Jonnitto.PrettyEmbedVideoPlatforms:ReplaceIframes`. The `content` property is per default set to `${value}`. +If you want to parse existing content with iframes and replace them automatically, you can add + [`Jonnitto.PrettyEmbed:ReplaceIframes`] with an `@process` like that: + `@process.replaceIframes = Jonnitto.PrettyEmbed:ReplaceIframes`. The `content` property is per default set to `${value}`. ## Get metadata -To get the metadata, you can run the flow command `./flow prettyembed:metadata`. This command search for nodes with the `VideoID` mixin, and tries to get the metadata. If for some reason, it is not possible to fetch the metadata (Perhaps the video is set to private, or the ID does not exist), you will get a table with the name of the node type, the type, the video ID and the node path. +To get the metadata, you can run the flow command `./flow prettyembed:metadata`. This command search for nodes with +the `VideoID` mixin, and tries to get the metadata. If for some reason, it is not possible to fetch the metadata +(Perhaps the video is set to private, or the ID does not exist), you will get a table with the name of the node type, +the type, the video ID and the node path. + The task comes with two options: - `--workspace` Workspace name, default is 'live' @@ -331,6 +294,7 @@ This package is member of the [PrettyEmbedCollection] which contains following p If you install the PrettyEmbedCollection, the video players get grouped into an own group in the node-inspector; otherwise, they will be in the default group. +[screenshot]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideoPlatforms/assets/4510166/adb7571a-3563-45cc-9318-ca27654b720d [packagist]: https://packagist.org/packages/jonnitto/prettyembedvideoplatforms [latest stable version]: https://poser.pugx.org/jonnitto/prettyembedvideoplatforms/v/stable [total downloads]: https://poser.pugx.org/jonnitto/prettyembedvideoplatforms/downloads @@ -357,8 +321,6 @@ If you install the PrettyEmbedCollection, the video players get grouped into an [prettyembedvideo]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideo [prettyembedvideoplatforms]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideoPlatforms [jonnitto.plyr]: https://github.com/jonnitto/Jonnitto.Plyr -[`jonnitto.prettyembedvideoplatforms:component.video`]: Resources/Private/Fusion/Component/Video.fusion -[`jonnitto.prettyembedvideoplatforms:content.video`]: Resources/Private/Fusion/Content/Video.fusion -[`jonnitto.prettyembedvideoplatforms:replaceiframes`]: Resources/Private/Fusion/ReplaceIframes.fusion +[`jonnitto.prettyembedvideoplatforms:content.video`]: Resources/Private/Fusion/Content.Video.fusion [sitegeist.slipstream]: https://github.com/sitegeist/Sitegeist.Slipstream [`main.scss`]: https://github.com/jonnitto/Jonnitto.PrettyEmbedHelper/blob/master/Resources/Private/Assets/Main.scss From 4d78f81465922a8302bd58729b6227f8b51fbaa4 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 19:26:12 +0100 Subject: [PATCH 16/20] Update: Set dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aa6fca7..8af5547 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ } ], "require": { - "jonnitto/prettyembedhelper": "^5.0 || dev-master" + "jonnitto/prettyembedhelper": "^6.0 || dev-master" }, "autoload": { "psr-4": { From 7f82e50f624cf1229fdb568f4ab323534e6cb00f Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Mon, 11 Dec 2023 19:53:00 +0100 Subject: [PATCH 17/20] Doce: Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e495689..f20f751 100644 --- a/README.md +++ b/README.md @@ -259,8 +259,8 @@ If you want to use the player as a pure component, you can use the `Jonnitto.Pre If you want to read the node properties and let the package handle all for you, you should use the [`Jonnitto.PrettyEmbedVideoPlatforms:Content.Video`] prototype. For more comfortable including in your node types, you can disable the content element wrapping with `contentElement = false`. This is useful if you want to create, for example, a text with a video node type. If you want to parse existing content with iframes and replace them automatically, you can add - [`Jonnitto.PrettyEmbed:ReplaceIframes`] with an `@process` like that: - `@process.replaceIframes = Jonnitto.PrettyEmbed:ReplaceIframes`. The `content` property is per default set to `${value}`. +[`Jonnitto.PrettyEmbed:ReplaceIframes`] with an `@process` like that: +`@process.replaceIframes = Jonnitto.PrettyEmbed:ReplaceIframes`. The `content` property is per default set to `${value}`. ## Get metadata From 91d475ccf5dd45d1251b1e0e6f8d7169797d85b2 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Tue, 12 Dec 2023 15:30:07 +0100 Subject: [PATCH 18/20] Update: Debug output --- Resources/Private/Fusion/Content.Video.fusion | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion index 9fd7a7f..a89c654 100644 --- a/Resources/Private/Fusion/Content.Video.fusion +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -8,6 +8,7 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto wrapper = ${PropTypes.anyOf(PropTypes.string, PropTypes.boolean)} image = ${PropTypes.instanceOf('Neos\Media\Domain\Model\ImageInterface')} async = ${PropTypes.boolean} + debug = ${PropTypes.boolean} metadata = ${PropTypes.shape({ 'videoID': PropTypes.anyOf(PropTypes.string, PropTypes.integer), 'title': PropTypes.string, @@ -165,7 +166,7 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto renderer = Neos.Fusion:Case { @process.debug = Neos.Fusion:Debug.Console { - @if.debug = ${props._debug} + @if.debug = ${props.debug} props = ${props} } noVideoID { From 68d0cd578dcbbc028b82daded1218bb5a406651c Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Tue, 12 Dec 2023 15:44:59 +0100 Subject: [PATCH 19/20] Update: Ad debug output --- Resources/Private/Fusion/Content.Video.fusion | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Private/Fusion/Content.Video.fusion b/Resources/Private/Fusion/Content.Video.fusion index a89c654..560611d 100644 --- a/Resources/Private/Fusion/Content.Video.fusion +++ b/Resources/Private/Fusion/Content.Video.fusion @@ -167,6 +167,7 @@ prototype(Jonnitto.PrettyEmbedVideoPlatforms:Content.Video) < prototype(Jonnitto renderer = Neos.Fusion:Case { @process.debug = Neos.Fusion:Debug.Console { @if.debug = ${props.debug} + package = 'PrettyEmbedVideoPlatforms' props = ${props} } noVideoID { From fdc9e7e971a452bafa14516160624c7d98dbb950 Mon Sep 17 00:00:00 2001 From: Jon Uhlmann Date: Tue, 12 Dec 2023 23:10:25 +0100 Subject: [PATCH 20/20] Docs: Update Readme --- README.md | 244 ++---------------------------------------------------- 1 file changed, 8 insertions(+), 236 deletions(-) diff --git a/README.md b/README.md index f20f751..a3e9091 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # Jonnitto.PrettyEmbedVideoPlatforms +**For a detail guide, please visit the [PrettyEmbed Wiki](https://github.com/jonnitto/Jonnitto.PrettyEmbedHelper/wiki)** + Prettier embeds for your Vimeo videos and YouTube videos/playlists in [Neos CMS] - with helpful options like high-res preview images, lightbox feature, and advanced customization of embed options. @@ -18,13 +20,17 @@ preview images, lightbox feature, and advanced customization of embed options. ## Installation -Most of the time, you have to make small adjustments to a package (e.g., configuration in `Settings.yaml`). Because of that, it is essential to add the corresponding package to the composer from your theme package. Mostly this is the site package located under `Packages/Sites/`. To install it correctly go to your theme package (e.g.`Packages/Sites/Foo.Bar`) and run following command: +Most of the time, you have to make small adjustments to a package (e.g., configuration in `Settings.yaml`). Because of +that, it is essential to add the corresponding package to the composer from your theme package. Navigate to this package +in your CLI and run the following command: ```bash composer require jonnitto/prettyembedvideoplatforms --no-update ``` -The `--no-update` command prevent the automatic update of the dependencies. After the package was added to your theme `composer.json`, go back to the root of the Neos installation and run `composer update`. Et voilà! Your desired package is now installed correctly. +The `--no-update` command prevent the automatic update of the dependencies. After the package was added to your package +`composer.json`, go back to the root of the Neos installation and run `composer update`. Et voilà! Your desired package +is now installed correctly. ## FAQ @@ -46,236 +52,6 @@ The `--no-update` command prevent the automatic update of the dependencies. Afte All packages from the PrettyEmbed series have the benefit of a better frontend performance since the player gets only loaded on request. So, no iframe/video gets loaded until the user wants to watch a video. -## Customization - -### Global settings for the whole PrettyEmbed series - -The settings will be set globally from the [PrettyEmbedHelper] package. These are the default settings for this package: - -```yaml -Jonnitto: - PrettyEmbed: - # If you have your own AlpineJS in your setup, you can disable the check here. Alpine must be an global variable - includeAlpineJsCheck: true - - # If you want to use your own assets, set this to false - includeAssets: - css: true - js: true - - # Can be `lazy`, `eager` or `null` - loadImageStrategy: lazy - - # If this is set to a string, the element gets wrapped with a div and the class with the giving string. - # If set to true, the element gets wrapped with a div without any class. - # If set to false, the element get not wrapped at all - wrapper: false - - # The buttons which get injected (file content) to the player. - # You can also overwrite the button Fusion components - button: - play: "resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PlayButton.svg" - pause: "resource://Jonnitto.PrettyEmbedHelper/Public/Assets/PauseButton.svg" - - # This is the maximum width of a custom preview image - maximumWidth: 1920 - - # Settings for the vimeo player - Vimeo: - # Set to `false` to disable the gdpr message, set to `popup` open the video in a new window or set to `true` to show the message in the player - gdprHandling: true - - # The hexadecimal color value of the playback controls, which is normally 00ADEF. - color: false - - # Show the controls or not - controls: true - - # Whether the player is in background mode, which hides the playback controls, enables autoplay, and loops the video. - background: false - - # Whether to restart the video automatically after reaching the end. - loop: false - - # Should the video be opened on a lightbox? Per default this is set via the node properties - lightbox: false - - # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties - preserveAspectRatio: true - - # If no aspect ratio can be calcualted from the oembed service, you have the possibility to set a fallback aspect ratio. - fallbackAspectRatio: "16 / 9" - - YouTube: - # Set to false to disable the gdpr message, set to popup open the video in a new window or set to true to show the message in the player - gdprHandling: true - - # If you want to save the duration of YouTube videos and playlists into the - # property metadataDuration you have to add a API key from YouTube Data API v3 - # You can create this key on https://console.cloud.google.com/ - # This key is only used in the backend - apiKey: null - - # Show the controls or not - controls: true - - # Whether to restart the video automatically after reaching the end. - loop: false - - # Should the video be opened on a lightbox? Per default this is set via the node properties - lightbox: false - - # When the lightbox is set, should the preview image preserve his aspect ratio? Per default this is set via the node properties - preserveAspectRatio: true - - # If no aspect ratio can be calcualted from the oembed service, you have the possibility to set a fallback aspect ratio. - fallbackAspectRatio: "16 / 9" -``` - -#### Disable inclusion of the CSS and/or JS files - -The Javascript and CSS files get loaded via [Sitegeist.Slipstream]: - -If you want to load your own CSS, you can disable it like that: - -```yaml -Jonnitto: - PrettyEmbed: - includeAssets: - css: false -``` - -If you want to load your own Javascript, you can disable it like that: - -```yaml -Jonnitto: - PrettyEmbed: - includeAssets: - js: false -``` - -If you use SCCS in your build pipeline, you can adjust the look and feel of [`Main.scss`] with following variables: - -```scss -// Buttons (play / pause) -$prettyembed-button-play-size: 72px !default; -$prettyembed-button-pause-size: calc( - $prettyembed-button-play-size / 2 -) !default; -$prettyembed-button-pause-margin: calc( - $prettyembed-button-pause-size / 2 -) !default; -$prettyembed-button-opacity: 0.9 !default; -$prettyembed-button-scale: 0.8 !default; -$prettyembed-button-scale-hover: 1 !default; -$prettyembed-button-scale-active: 0.9 !default; -$prettyembed-button-foreground-color: #fff !default; -$prettyembed-button-background-color: #000 !default; -$prettyembed-button-background-opactiy: 0.4 !default; - -// Lightbox -$prettyembed-lightbox-include: true !default; -$prettyembed-lightbox-overlay-color: #0b0b0b !default; -$prettyembed-lightbox-overlay-opacity: 0.8 !default; -$prettyembed-lightbox-padding: 15px !default; -$prettyembed-lightbox-max-width: 900px !default; -$prettyembed-lightbox-shadow: 0 0 8px rgba(#000, 0.6) !default; -$prettyembed-lightbox-z-index: 5500 !default; -$prettyembed-lightbox-close-size: 30px !default; -$prettyembed-lightbox-close-opacity: 0.65 !default; -$prettyembed-lightbox-close-opacity-hover: 1 !default; -$prettyembed-lightbox-close-color: #fff !default; -$prettyembed-lightbox-backdrop-filter: blur(5px) !default; - -// GDPR Message -$prettyembed-gdpr-include: true !default; -$prettyembed-gdpr-color: #fff !default; -$prettyembed-gdpr-font-size-breakpoint: 640px !default; -$prettyembed-gdpr-font-size-mobile: 0.8rem !default; -$prettyembed-gdpr-font-size: 1rem !default; -$prettyembed-gdpr-gap: 1em !default; -$prettyembed-gdpr-padding: 0.5em !default; -$prettyembed-gdpr-explantation-font-size: 0.9em !default; -$prettyembed-gdpr-explantation-max-width: 60ch !default; -$prettyembed-gdpr-button-gap: 1em !default; -$prettyembed-gdpr-button-padding: 0.5em 1em !default; -$prettyembed-gdpr-button-border-radius: 0.25em !default; - -$prettyembed-gdpr-button-accept-color: #fff !default; -$prettyembed-gdpr-button-accept-background-color: #16a34a !default; -$prettyembed-gdpr-button-accept-border: 1px solid #16a34a !default; -$prettyembed-gdpr-button-accept-color-hover: #fff !default; -$prettyembed-gdpr-button-accept-background-color-hover: #15803d !default; -$prettyembed-gdpr-button-accept-border-color-hover: #15803d !default; - -$prettyembed-gdpr-button-external-color: #fff !default; -$prettyembed-gdpr-button-external-background-color: transparent !default; -$prettyembed-gdpr-button-external-border: 1px solid #fff !default; -$prettyembed-gdpr-button-external-color-hover: #000 !default; -$prettyembed-gdpr-button-external-background-color-hover: #fff !default; -$prettyembed-gdpr-button-external-border-color-hover: false !default; - -$prettyembed-gdpr-backdrop-filter: blur(5px) !default; -$prettyembed-gdpr-overlay-color: #0b0b0b !default; -$prettyembed-gdpr-overlay-opacity: 0.8 !default; -``` - -Because all variables have the `!default` flag, the variables don't get overwritten if you declare -them before you import [`Main.scss`]. Like that, most of the frequent adjustments can be easily achieved. - -### NodeTypes and Mixins - -If you want to customize the default settings, take a look at the `Settings.Jonnitto.yaml` from [PrettyEmbedHelper] -file. If no node property is given, these default values will be taken. If you, for example, want to let the editor -choose if the video is has the controls from the platform, you can activate the mixin in your file where you override -node types like that: - -```yaml -"Jonnitto.PrettyEmbedVideoPlatforms:Content.Video": - superTypes: - "Jonnitto.PrettyEmbedHelper:Mixin.Controls": true -``` - -These are the available mixins: - -| Mixin name (Prefix: `Jonnitto.PrettyEmbed`) | Description | Default value | Enabled per default | -| ------------------------------------------- | --------------------------------------------------------------------------- | :-----------: | :-----------------: | -| `Helper:Mixin.Groups` | Enables the inspector groups | | ✓ | -| `Helper:Mixin.Image` | Add the preview image property | | ✓ | -| `Helper:Mixin.Lightbox` | Open the video in a lightbox | `false` | ✓ | -| `Helper:Mixin.PreserveAspectRatio` | If the lightbox is active, the preview image can preserve his aspect ratio. | `true` | ✓ | -| `Helper:Mixin.BackendLabel` | Read the title of the video and set this as label in the content tree | | ✓ | -| `VideoPlatforms:Mixin.VideoID` | Let the user enter the video ID or the URL | | ✓ | -| `Helper:Mixin.Loop` | Loop the video | `false` | | -| `Helper:Mixin.Controls` | Show the controls | `true` | | - -If you want to include the video in your node type, you should use at least the mixin `Jonnitto.PrettyEmbedVideoPlatforms:Mixin.VideoID`. This add besides the `videoID` property also the properties for the metadata fetched from the oembed service. This mixin is also necessary to fetch/update the data from the service. - -### Fusion - -If you want to use the player as a pure component, you can use the `Jonnitto.PrettyEmbed:Presentation.YouTube` or -`Jonnitto.PrettyEmbed:Presentation.Vimeo` Fusion prototype. - -If you want to read the node properties and let the package handle all for you, you should use the [`Jonnitto.PrettyEmbedVideoPlatforms:Content.Video`] prototype. For more comfortable including in your node types, you can disable the content element wrapping with `contentElement = false`. This is useful if you want to create, for example, a text with a video node type. - -If you want to parse existing content with iframes and replace them automatically, you can add -[`Jonnitto.PrettyEmbed:ReplaceIframes`] with an `@process` like that: -`@process.replaceIframes = Jonnitto.PrettyEmbed:ReplaceIframes`. The `content` property is per default set to `${value}`. - -## Get metadata - -To get the metadata, you can run the flow command `./flow prettyembed:metadata`. This command search for nodes with -the `VideoID` mixin, and tries to get the metadata. If for some reason, it is not possible to fetch the metadata -(Perhaps the video is set to private, or the ID does not exist), you will get a table with the name of the node type, -the type, the video ID and the node path. - -The task comes with two options: - -- `--workspace` Workspace name, default is 'live' -- `--remove` Is set, all metadata will be removed - -To get an overview of the options in the cli, you can run `./flow help prettyembed:metadata` - ## Merge PrettyEmbedYoutube and PrettyEmbedVimeo If you want existing nodes from [PrettyEmbedYoutube] and [PrettyEmbedVimeo] use this package, @@ -317,10 +93,6 @@ If you install the PrettyEmbedCollection, the video players get grouped into an [prettyembedcollection]: https://github.com/jonnitto/Jonnitto.PrettyembedCollection [prettyembedvimeo]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVimeo [prettyembedyoutube]: https://github.com/jonnitto/Jonnitto.PrettyEmbedYoutube -[prettyembedhelper]: https://github.com/jonnitto/Jonnitto.PrettyEmbedHelper [prettyembedvideo]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideo [prettyembedvideoplatforms]: https://github.com/jonnitto/Jonnitto.PrettyEmbedVideoPlatforms [jonnitto.plyr]: https://github.com/jonnitto/Jonnitto.Plyr -[`jonnitto.prettyembedvideoplatforms:content.video`]: Resources/Private/Fusion/Content.Video.fusion -[sitegeist.slipstream]: https://github.com/sitegeist/Sitegeist.Slipstream -[`main.scss`]: https://github.com/jonnitto/Jonnitto.PrettyEmbedHelper/blob/master/Resources/Private/Assets/Main.scss