trix_embed 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +120 -47
- data/app/assets/builds/trix-embed.js +38 -19
- data/app/assets/builds/trix-embed.metafile.json +1 -1
- data/app/javascript/controller.js +342 -145
- data/app/javascript/enumerable.js +19 -0
- data/app/javascript/forms.js +134 -0
- data/app/javascript/guard.js +29 -47
- data/app/javascript/index.js +9 -3
- data/app/javascript/media.js +12 -2
- data/app/javascript/metadata.js +4 -0
- data/app/javascript/renderer.js +155 -75
- data/app/javascript/store.js +13 -1
- data/app/javascript/templates.js +45 -28
- data/app/javascript/urls.js +57 -42
- data/app/models/trix_embed/attachment.rb +20 -6
- data/app/views/action_text/contents/_content.html.erb +1 -1
- data/lib/trix_embed/engine.rb +1 -1
- data/lib/trix_embed/version.rb +1 -1
- metadata +37 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d839c80df9c7dc70b3336dccb40896128aadff60d97fc7d4ceb5d7afe14fe87a
|
4
|
+
data.tar.gz: 56632a5f6852a5ea1d03348f724d96bc93cd306a497fa5e776660ab355ad8708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35e20db3bea5b867c1b5c9c0ddff48b7055670a11d78c94b299d4c1d9340082084d2cf2ad7c68eab6ae3a66f289a6b664ace9a6ca65c74664816d54203e4aa45
|
7
|
+
data.tar.gz: d588233eb5e1d897dfdfc02fa40d65896e009698393db4fbd23221fd8e25fc1fa1a07e71545b04aa8083fde4af5e0be191f654c5ce0e95a49918a56a0ee65547
|
data/README.md
CHANGED
@@ -1,15 +1,41 @@
|
|
1
1
|
# Trix Embed
|
2
2
|
|
3
|
-
|
3
|
+
#### Take control over what external links and embedded media is permitted in the Trix editor via copy/paste
|
4
|
+
|
5
|
+
<!-- Tocer[start]: Auto-generated, don't remove. -->
|
6
|
+
|
7
|
+
## Table of Contents
|
8
|
+
|
9
|
+
- [Setup](#setup)
|
10
|
+
- [Features](#features)
|
11
|
+
- [Allow / Block Lists](#allow--block-lists)
|
12
|
+
- [Template Overrides](#template-overrides)
|
13
|
+
- [Basic Usage](#basic-usage)
|
14
|
+
- [Allow Lists](#allow-lists)
|
15
|
+
- [Block Lists](#block-lists)
|
16
|
+
- [Sponsors](#sponsors)
|
17
|
+
- [Developing](#developing)
|
18
|
+
- [Releasing](#releasing)
|
19
|
+
- [License](#license)
|
20
|
+
|
21
|
+
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
22
|
+
|
23
|
+
## Dependencies
|
24
|
+
|
25
|
+
- [ActionText](https://github.com/rails/rails/tree/main/actiontext)
|
26
|
+
- [Stimulus](https://github.com/hotwired/stimulus)
|
27
|
+
- [Trix](https://github.com/basecamp/trix)
|
4
28
|
|
5
29
|
## Setup
|
6
30
|
|
7
31
|
```sh
|
8
|
-
|
32
|
+
bundle add trix_embed
|
33
|
+
yarn add trix-embed@$(bundle show trix_embed | ruby -ne 'puts $_.split(/-/).last')
|
9
34
|
```
|
10
35
|
|
11
36
|
```js
|
12
|
-
import 'trix'
|
37
|
+
import Trix from 'trix'
|
38
|
+
import "@rails/actiontext"
|
13
39
|
import { Application, Controller } from '@hotwired/stimulus'
|
14
40
|
import TrixEmbed from 'trix-embed'
|
15
41
|
|
@@ -17,18 +43,93 @@ const application = Application.start()
|
|
17
43
|
TrixEmbed.initialize({ application, Controller, Trix })
|
18
44
|
```
|
19
45
|
|
20
|
-
##
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
46
|
+
## Features
|
47
|
+
|
48
|
+
### Allow / Block Lists
|
49
|
+
|
50
|
+
Configure allow and/or block lists for external links and embedded media in your Trix editors.
|
51
|
+
|
52
|
+
__⚠︎ Block lists have precendence!__
|
53
|
+
|
54
|
+
- allowed link hosts
|
55
|
+
- blocked link hosts
|
56
|
+
- allowed media hosts
|
57
|
+
- blocked media hosts
|
58
|
+
|
59
|
+
_Note that you can also use wildcards `*` in any of lists._
|
60
|
+
|
61
|
+
### Template Overrides
|
62
|
+
|
63
|
+
TODO: document...
|
64
|
+
|
65
|
+
## Basic Usage
|
66
|
+
|
67
|
+
### Allow Lists
|
68
|
+
|
69
|
+
- Allow everything
|
70
|
+
|
71
|
+
```html
|
72
|
+
<form>
|
73
|
+
<input id="content" name="content" type="hidden">
|
74
|
+
<trix-editor id="editor" input="content"
|
75
|
+
data-controller="trix-embed"
|
76
|
+
data-trix-embed-allowed-link-hosts-value='["*"]'
|
77
|
+
data-trix-embed-allowed-media-hosts-value='["*"]'>
|
78
|
+
</trix-editor>
|
79
|
+
</form>
|
80
|
+
```
|
81
|
+
|
82
|
+
- Allow links to all hosts and allow media (images, videos, etc.) from the following hosts: `vimeo.com, voomly.com, youtube.com`
|
83
|
+
|
84
|
+
```html
|
85
|
+
<form>
|
86
|
+
<input id="content" name="content" type="hidden">
|
87
|
+
<trix-editor id="editor" input="content"
|
88
|
+
data-controller="trix-embed"
|
89
|
+
data-trix-embed-allowed-link-hosts-value='["*"]'
|
90
|
+
data-trix-embed-allowed-media-hosts-value='["vimeo.com", "voomly.com", "youtube.com"]'>
|
91
|
+
</trix-editor>
|
92
|
+
</form>
|
93
|
+
```
|
94
|
+
|
95
|
+
### Block Lists
|
96
|
+
|
97
|
+
- Block everything
|
98
|
+
|
99
|
+
```html
|
100
|
+
<form>
|
101
|
+
<input id="content" name="content" type="hidden">
|
102
|
+
<trix-editor id="editor" input="content"
|
103
|
+
data-controller="trix-embed"
|
104
|
+
data-trix-embed-block-link-hosts-value='["*"]'
|
105
|
+
data-trix-embed-block-media-hosts-value='["*"]'>
|
106
|
+
</trix-editor>
|
107
|
+
</form>
|
108
|
+
```
|
109
|
+
|
110
|
+
...or simply.
|
111
|
+
|
112
|
+
```html
|
113
|
+
<form>
|
114
|
+
<input id="content" name="content" type="hidden">
|
115
|
+
<trix-editor id="editor" input="content" data-controller="trix-embed">
|
116
|
+
</trix-editor>
|
117
|
+
</form>
|
118
|
+
```
|
119
|
+
|
120
|
+
- Block links to the following hosts: `4chan.org, 8chan.net, thepiratebay.org`
|
121
|
+
and block media (images, videos, etc.) from the following hosts: `deviantart.com, imgur.com, tumblr.com`
|
122
|
+
|
123
|
+
```html
|
124
|
+
<form>
|
125
|
+
<input id="content" name="content" type="hidden">
|
126
|
+
<trix-editor id="editor" input="content"
|
127
|
+
data-controller="trix-embed"
|
128
|
+
data-trix-embed-blocked-link-hosts-value='["4chan.org", "8chan.net", "thepiratebay.org"]'
|
129
|
+
data-trix-embed-blocked-media-hosts-value='["deviantart.com", "imgur.com", "tumblr.com"]'>
|
130
|
+
</trix-editor>
|
131
|
+
</form>
|
132
|
+
```
|
32
133
|
|
33
134
|
## Sponsors
|
34
135
|
|
@@ -46,45 +147,17 @@ TrixEmbed.initialize({ application, Controller, Trix })
|
|
46
147
|
```sh
|
47
148
|
git clone https://github.com/hopsoft/trix_embed.git
|
48
149
|
cd trix_embed
|
49
|
-
|
50
|
-
yarn build
|
51
|
-
yarn dev
|
150
|
+
bin/dev
|
52
151
|
```
|
53
|
-
### Docker
|
54
|
-
|
55
|
-
This project supports a fully Dockerized development experience.
|
56
|
-
|
57
|
-
1. Simply run the following commands to get started.
|
58
|
-
|
59
|
-
```sh
|
60
|
-
git clone -o github https://github.com/hopsoft/trix_embed.git
|
61
|
-
cd trix_embed
|
62
|
-
```
|
63
|
-
|
64
|
-
```sh
|
65
|
-
docker compose up -d # start the envionment (will take a few minutes on 1st run)
|
66
|
-
open http://localhost:3000 # in a browser
|
67
|
-
```
|
68
|
-
|
69
|
-
And, if you're using the [containers gem (WIP)](https://github.com/hopsoft/containers).
|
70
|
-
|
71
|
-
```sh
|
72
|
-
containers up # start the envionment (will take a few minutes on 1st run)
|
73
|
-
open http://localhost:3000 # in a browser
|
74
|
-
```
|
75
|
-
|
76
|
-
1. Edit files using your preferred tools on the host machine.
|
77
|
-
|
78
|
-
1. That's it!
|
79
152
|
|
80
153
|
## Releasing
|
81
154
|
|
82
155
|
1. Run `yarn` and `bundle` to pick up the latest
|
83
|
-
1. Bump version
|
84
|
-
1. Run `yarn build`
|
156
|
+
1. Bump version numbers at `lib/trix_embed/version.rb` and `package.json` _(make sure they match)_. Pre-release versions use `.preN`
|
157
|
+
1. Run `yarn build` - *builds both the Ruby gem and the NPM package*
|
85
158
|
1. Commit and push changes to GitHub
|
86
159
|
1. Run `rake release`
|
87
|
-
1. Run `yarn publish --no-git-tag-version --access public`
|
160
|
+
1. Run `yarn publish --new-version X.X.X --no-git-tag-version --access public`
|
88
161
|
1. Yarn will prompt you for the new version. Pre-release versions use `-preN`
|
89
162
|
1. Commit and push changes to GitHub
|
90
163
|
1. Create a new release on GitHub ([here](https://github.com/hopsoft/trix_embed/releases)) and generate the changelog for the stable release for it
|
@@ -1,22 +1,41 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
/*
|
2
|
+
trix-embed 0.0.3 (MIT)
|
3
|
+
Copyright © 2023 Nate Hopkins (hopsoft) <natehop@gmail.com>
|
4
|
+
*/
|
5
|
+
var ge=Object.defineProperty,be=Object.defineProperties;var ye=Object.getOwnPropertyDescriptors;var B=Object.getOwnPropertySymbols;var xe=Object.prototype.hasOwnProperty,we=Object.prototype.propertyIsEnumerable;var N=(r,e,t)=>e in r?ge(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,E=(r,e)=>{for(var t in e||(e={}))xe.call(e,t)&&N(r,t,e[t]);if(B)for(var t of B(e))we.call(e,t)&&N(r,t,e[t]);return r},L=(r,e)=>be(r,ye(e));var J=(r,e,t)=>(N(r,typeof e!="symbol"?e+"":e,t),t);var _={version:"0.0.3"};var R={name:"AES-GCM",length:256},ve=!0,Ee=["encrypt","decrypt"];async function Le(){let e=["encrypt","decrypt"];return await crypto.subtle.generateKey(R,!0,e)}async function Te(r){let e=await crypto.subtle.exportKey("jwk",r);return JSON.stringify(e)}async function G(r){let e=JSON.parse(r);return await crypto.subtle.importKey("jwk",e,R,ve,Ee)}async function Se(r,e){let t=new TextEncoder().encode(String(r)),n=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt(L(E({},R),{iv:n}),e,t),s={ciphertext:btoa(String.fromCharCode(...new Uint8Array(i))),iv:btoa(String.fromCharCode(...n))};return btoa(JSON.stringify(s))}async function Ae(r,e){let t=JSON.parse(atob(r)),n=new Uint8Array(atob(t.ciphertext).split("").map(a=>a.charCodeAt(0))),i=new Uint8Array(atob(t.iv).split("").map(a=>a.charCodeAt(0))),s=await crypto.subtle.decrypt(L(E({},R),{iv:i}),e,n);return new TextDecoder().decode(s)}async function T(){let r=await Le(),e=await Te(r);return btoa(e)}async function x(r,e=[]){let t=await G(atob(r));return Promise.all(e.map(n=>Se(n,t)))}async function X(r,e=[]){let t=await G(atob(r));return Promise.all(e.map(n=>Ae(n,t)))}async function Q(r=[]){let e=await T(),t=await x(e,r);return console.log(`data-trix-embed-key-value="${e}"`),console.log(`data-trix-embed-hosts-value='${JSON.stringify(t)}'`),{key:e,encryptedValues:t}}var Y=r=>Math.floor(Math.random()*r),w=(r,e=null)=>{let t=[...r];e==="all"&&(e=t.length);let n=t.length,i=[],s=new Set;for(;i.length<e;){let a=Y(n);for(;s.has(a);)a=Y(n);s.add(a),i.push(t[a])}return typeof e=="number"?i:i[0]};function b(r,e=t=>{}){try{let t=new URL(String(r).trim());return t&&e&&e(t),t}catch(t){console.info(`Failed to parse URL! value='${r}']`)}return null}function Z(r,e=t=>{}){var n;let t=(n=b(r))==null?void 0:n.host;return t&&e&&e(t),t}function O(r){return document.createTreeWalker(r,NodeFilter.SHOW_TEXT,e=>e.nodeValue.match(/http/gi)?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP)}function ke(r){let e=new Set,t=O(r),n;for(;n=t.nextNode();)n.nodeValue.split(/\s+/).filter(i=>i.startsWith("http")).forEach(i=>b(i,s=>e.add(s.href)));return[...e]}function U(r){if(r.src){let e=r.src.trim();if(e.length)return e}if(r.href){let e=r.href.trim();if(e.length)return e}return""}function Re(r){let e=new Set;return r.src&&b(r.src,n=>e.add(n.href)),r.href&&b(r.href,n=>e.add(n.href)),r.querySelectorAll("[src], [href]").forEach(n=>b(U(n),i=>e.add(i.href))),[...e]}function C(r,e=[],t=[]){let n=Z(r);return t.includes("*")||t.find(i=>n.endsWith(i))?!1:!!(e.find(i=>n.endsWith(i))||e.includes("*")&&(n||r.startsWith("data:")||r.startsWith("news:")||r.startsWith("tel:")))}function ee(r){return[...r.reduce((e,t)=>(Z(t,n=>e.add(n)),e),new Set)]}function te(r){let e=Re(r),t=ke(r);return[...new Set([...e,...t])]}var re={attachment:"trix-embed/attachment"};var ie={avif:"image/avif",bmp:"image/bmp",gif:"image/gif",heic:"image/heic",heif:"image/heif",ico:"image/x-icon",jp2:"image/jp2",jpeg:"image/jpeg",jpg:"image/jpeg",jxr:"image/vnd.ms-photo",png:"image/png",svg:"image/svg+xml",tif:"image/tiff",tiff:"image/tiff",webp:"image/webp"};var Ue=ie,Me=["animate","animateMotion","animateTransform","area","audio","base","embed","feDisplacementMap","feImage","feTile","filter","font-face-uri","iframe","image","link","object","script","source","track","use","video"],Ne=["audio","embed","iframe","img","input","script","source","track","video","frame","frameset","object","picture","use"],ne="trix-editor",se="action-text-attachment",ae=Me.concat(Ne);function oe(r){return!!Object.values(ie).find(e=>e===P(r))}function P(r){let e;if(e=b(r),!e)return null;let t=e.pathname.lastIndexOf(".");if(!t)return null;let n=e.pathname.substring(t+1);return Ue[n]}var j,H,ce=new Set,Oe=`${ne}[data-controller~="trix-embed"]`;function de(r){var n;let{method:e,action:t}=r||{};return t=((n=b(t))==null?void 0:n.pathname)||t,`${e}:${t}`.trim().toLowerCase()}function me(r,e){if(!r)return;let t=de(r);ce.add({key:t,form:r,input:e})}function Ce(r){var l;let e=de(r),t=[...ce].filter(o=>o.key===e);if(!t.length)return!0;if(r.trixEmbedPasting)return!1;if(r.querySelector(Oe))return!0;let n=new FormData(r),i=((l=b(r.action))==null?void 0:l.searchParams)||new URLSearchParams;return!t.map(o=>o.input).map(o=>!(o.name&&(n.has(o.name)||i.has(o.name))||o.id&&(n.has(o.id)||i.has(o.id)))).includes(!1)}function le(r){Ce(r.target)||r.preventDefault()}function F(r){r.removeEventListener("submit",le,!0),r.addEventListener("submit",le,!0)}function Pe(){if(j)return;let r=Document.prototype.createElement;j={value:function(){let e=r.apply(this,arguments);try{String(arguments[0]).toUpperCase()==="FORM"&&F(e)}catch(t){}return e},configurable:!1},Object.defineProperty(Document.prototype,"createElement",j)}function D(r=0){if(!document.body&&r<10)return setTimeout(()=>D(r+1),50);H||(H=new MutationObserver(e=>e.forEach(t=>t.addedNodes.forEach(n=>{n instanceof HTMLFormElement&&F(n)}))),H.observe(document.body,{childList:!0,subtree:!0}))}addEventListener("load",()=>D());Pe();D();document.querySelectorAll("form").forEach(r=>F(r));var S=class{constructor(e){this.controller=e}preventAttachments(){var e,t,n,i,s;(e=this.editor)==null||e.removeAttribute("data-direct-upload-url"),(t=this.editor)==null||t.removeAttribute("data-blob-url-template"),(n=this.editor)==null||n.addEventListener("trix-file-accept",a=>a.preventDefault(),!0),(s=(i=this.toolbar)==null?void 0:i.querySelector('[data-trix-button-group="file-tools"]'))==null||s.remove()}async preventLinks(){var n,i;let e=await this.controller.allowedLinkHosts;!(await this.controller.blockedLinkHosts).length&&e.includes("*")||(i=(n=this.toolbar)==null?void 0:n.querySelector('[data-trix-action="link"]'))==null||i.remove()}protect(e=0){if(!this.toolbar&&e<10)return setTimeout(()=>this.protect(e+1),25);this.preventAttachments(),this.preventLinks(),this.form&&me(this.form,this.input)}get editor(){return this.controller.element}get toolbar(){return this.controller.toolbarElement}get form(){return this.controller.formElement}get input(){return this.controller.inputElement}};var A=class{constructor(e){var n,i,s;let t=[location.pathname,(i=b((n=e.formElement)==null?void 0:n.action))==null?void 0:i.pathname,(s=e.element.closest("[id]"))==null?void 0:s.id];this.controller=e,this.identifier=t.filter(a=>a&&a.length).join("/").replace(/\/{2,}/g,"/"),this.base=this.obfuscate(this.identifier)}split(e){let t=Math.ceil(e.length/2);return[e.slice(0,t),e.slice(t)]}obfuscate(e){var i;let t=[...e].map(s=>s.charCodeAt(0));return[(i=this.split(t)[1])==null?void 0:i.reverse(),t[0]].flat().join("")}read(e){return sessionStorage.getItem(this.generateStorageKey(e))}write(e,t){return sessionStorage.setItem(this.generateStorageKey(e),t)}remove(e){return sessionStorage.removeItem(this.generateStorageKey(e))}generateStorageKey(e){let t=[...this.obfuscate(e)],[n,i]=this.split(t);return btoa(`${n}/${this.base}/${i}`)}};var V={link:"<a href='{{url}}'>{{label}}</a>",embedded:`
|
6
|
+
<span>
|
7
|
+
<strong>{{label}}</strong>
|
8
|
+
<span>{{description}}</span>
|
9
|
+
<del>{{url}}</del>
|
10
|
+
</span>
|
11
|
+
`,prohibited:`
|
12
|
+
<span>
|
13
|
+
<strong>{{label}}</strong>
|
14
|
+
<span>{{description}}</span>
|
15
|
+
<del>{{url}}</del>
|
16
|
+
</span>
|
17
|
+
`,error:`
|
18
|
+
<div data-trix-embed data-trix-embed-error>
|
19
|
+
<h1>{{header}}</h1>
|
20
|
+
<pre><code>{{error.stack}}</code></pre>
|
21
|
+
</div>
|
22
|
+
`,iframe:`
|
23
|
+
<div data-trix-embed>
|
24
|
+
<iframe src='{{src}}' loading='lazy' referrerpolicy='no-referrer' scrolling='no'></iframe>
|
25
|
+
</div>
|
26
|
+
`,image:`
|
27
|
+
<div data-trix-embed>
|
28
|
+
<img src='{{src}}' loading='lazy'></img>
|
29
|
+
</div>
|
30
|
+
`,warning:`
|
31
|
+
<div data-trix-embed data-trix-embed-warning>
|
32
|
+
<h1>{{header}}</h1>
|
33
|
+
<h3>{{subheader}}</h3>
|
5
34
|
|
6
|
-
<h2>
|
7
|
-
<ul
|
8
|
-
<li>Media is only supported from allowed hosts.</li>
|
9
|
-
</ul>
|
35
|
+
<h2>{{prohibited.header}}</h2>
|
36
|
+
<ul>{{prohibited.hosts}}</ul>
|
10
37
|
|
11
|
-
<h2>
|
12
|
-
<ul
|
13
|
-
<li>Allowed hosts not configured.</li>
|
14
|
-
</ul>
|
15
|
-
</div>
|
16
|
-
`,exception:`
|
17
|
-
<div style='background-color:lightyellow; color:red; border:solid 1px red; padding:20px;'>
|
18
|
-
<h1>Unhandled Exception!</h1>
|
19
|
-
<p>Show a programmer the message below.</p>
|
20
|
-
<pre style="background-color:darkslategray; color:whitesmoke; padding:10px;"><code></code></pre>
|
38
|
+
<h2>{{allowed.header}}</h2>
|
39
|
+
<ul>{{allowed.hosts}}</ul>
|
21
40
|
</div>
|
22
|
-
`};function z(n){let e=document.createElement("template");return e.innerHTML=me[n],e}var w=class{constructor(e){this.controller=e,this.initializeTempates()}initializeTempates(){["error","exception","header","iframe","image"].forEach(t=>this.initializeTemplate(t))}initializeTemplate(e){let t;this.controller[`has${e.charAt(0).toUpperCase()+e.slice(1)}TemplateValue`]&&(t=document.getElementById(this.controller[`${e}TemplateValue`])),this[`${e}Template`]=t||z(e)}renderHeader(e){let t=this.headerTemplate.content.firstElementChild.cloneNode(!0),i=t.tagName.match(/h1/i)?t:t.querySelector("h1");return i.innerHTML=e,t.outerHTML}renderLinks(e=["https://example.com","https://test.com"]){return e=e.filter(i=>{let r=!1;return h(i,o=>r=!0),r}).sort(),e.length?`<ul>${e.map(i=>`<li><a href='${i}'>${i}</a></li>`).join("")}</ul><br>`:void 0}renderEmbed(e="https://example.com"){let t;if(J(e)){t=this.imageTemplate.content.firstElementChild.cloneNode(!0);let i=t.tagName.match(/img/i)?t:t.querySelector("img");i.src=e}else{t=this.iframeTemplate.content.firstElementChild.cloneNode(!0);let i=t.tagName.match(/iframe/i)?t:t.querySelector("iframe");i.src=e}return t.outerHTML}renderEmbeds(e=["https://example.com","https://test.com"]){if(e!=null&&e.length)return e.map(t=>this.renderEmbed(t))}renderErrors(e=["https://example.com","https://test.com"],t=[]){if(!(e!=null&&e.length))return;let i=this.errorTemplate.content.firstElementChild.cloneNode(!0),r=i.querySelector('[data-list="prohibited-hosts"]'),o=i.querySelector('[data-list="allowed-hosts"]');if(r){let s=I(e).sort();s.length&&(r.innerHTML=s.map(a=>`<li>${a}</li>`).join(""))}return o&&t.length&&(o.innerHTML=t.map(s=>`<li>${s}</li>`).join("")),i.outerHTML}renderException(e){let t=this.exceptionTemplate.content.firstElementChild.cloneNode(!0),i=t.querySelector("code");return i.innerHTML=e.message,t.outerHTML}};var ue={Controller:null,Trix:null};function B(n=ue){var i;let{Controller:e,Trix:t}=n;return i=class extends e{async connect(){var r;this.store=new E(this),this.guard=new T(this),await this.rememberConfig(),this.paranoid&&this.guard.protect(),(r=this.toolbarElement.querySelector('[data-trix-button-group="file-tools"]'))==null||r.remove(),window.addEventListener("beforeunload",()=>this.disconnect())}disconnect(){this.paranoid&&this.guard.cleanup(),this.forgetConfig()}async paste(r){let{html:o,string:s,range:a}=r.paste,u=o||s||"",d=this.buildPastedTemplate(u),p=d.content.firstElementChild,l=this.sanitizePastedElement(p).innerHTML.trim(),y=q(p);if(!y.length)return;r.preventDefault(),this.editor.setSelectedRange(a);let C=await this.hosts,f=new w(this);try{let g=y.filter(c=>H(c));Array.from(d.content.firstElementChild.querySelectorAll("iframe")).forEach(c=>{g.includes(c.src)||g.push(c.src)});let k=g.filter(c=>R(c,C)),W=g.filter(c=>!k.includes(c)),j=y.filter(c=>!g.includes(c)),L=j.filter(c=>R(c,C)),_=j.filter(c=>!L.includes(c)),m;if(m=W,m.length&&await this.insert(f.renderErrors(m,C.sort())),m=_,m.length&&(await this.insert(f.renderHeader("Pasted URLs")),await this.insert(f.renderLinks(m),{disposition:"inline"})),m=k,m.length&&(m.length>1&&await this.insert(f.renderHeader("Embedded Media")),await this.insert(f.renderEmbeds(m))),m=L,m.length&&await this.insert(f.renderEmbeds(L)),k[0]===l||L[0]===l)return this.editor.insertLineBreak();l.length&&(await this.insert(f.renderHeader("Pasted Content",l)),this.editor.insertLineBreak(),this.insert(l,{disposition:"inline"}))}catch(g){this.insert(f.renderException(g))}}buildPastedTemplate(r){let o=document.createElement("template");return o.innerHTML=`<div>${r.trim()}</div>`,o}sanitizePastedElement(r){r=r.cloneNode(!0),r.querySelectorAll(F.join(", ")).forEach(a=>a.remove());let o=r.querySelectorAll("*"),s=r.innerHTML.match(/\r\n|\n|\r/g)||[];return(s.length?o.length/s.length:0)<=.1&&(r.innerHTML=r.innerHTML.replaceAll(/\r\n|\n|\r/g,"<br>")),r}insertAttachment(r,o={delay:0}){let{delay:s}=o;return new Promise(a=>{setTimeout(()=>{let u=new t.Attachment({content:r,contentType:"application/vnd.trix-embed"});this.editor.insertAttachment(u),a()},s)})}insertHTML(r,o={delay:0}){let{delay:s}=o;return new Promise(a=>{setTimeout(()=>{this.editor.insertHTML(r),this.editor.moveCursorInDirection("forward"),this.editor.insertLineBreak(),this.editor.moveCursorInDirection("backward"),a()},s)})}insert(r,o={delay:0,disposition:"attachment"}){let{delay:s,disposition:a}=o;return r!=null&&r.length?new Promise(u=>{setTimeout(()=>{if(typeof r=="string")return a==="inline"?this.insertHTML(r,{delay:s}).then(u):this.insertAttachment(r,{delay:s}).then(u);if(Array.isArray(r))return a==="inline"?r.reduce((d,p,x)=>d.then(this.insertHTML(p,{delay:s})),Promise.resolve()).then(u):r.reduce((d,p,x)=>d.then(this.insertAttachment(p,{delay:s})),Promise.resolve()).then(u);u()})}):Promise.resolve()}get editor(){return this.element.editor}get toolbarElement(){let r=this.element.previousElementSibling;return r!=null&&r.tagName.match(/trix-toolbar/i)?r:null}get inputElement(){return document.getElementById(this.element.getAttribute("input"))}get formElement(){return this.element.closest("form")}get paranoid(){return!!this.store.read("paranoid")}get key(){try{return JSON.parse(this.store.read("key"))[2]}catch(r){}}get hosts(){try{return K(this.key,JSON.parse(this.store.read("hosts")))}catch(r){return[]}}get reservedDomains(){return["example.com","test.com","invalid.com","example.cat","nic.example","example.co.uk"]}async rememberConfig(){let r=await v(),o=await b(r,this.reservedDomains),s=await b(r,this.hostsValue);this.store.write("key",JSON.stringify([o[0],o[1],r,o[2]])),this.element.removeAttribute("data-trix-embed-key-value"),this.store.write("hosts",JSON.stringify(s)),this.element.removeAttribute("data-trix-embed-hosts-value"),this.paranoidValue!==!1&&(this.store.write("paranoid",JSON.stringify(o.slice(3))),this.element.removeAttribute("data-trix-embed-paranoid"))}forgetConfig(){this.store.remove("key"),this.store.remove("hosts"),this.store.remove("paranoid")}},S(i,"values",{validTemplate:String,errorTemplate:String,headerTemplate:String,iframeTemplate:String,imageTemplate:String,hosts:Array,paranoid:{type:Boolean,default:!0}}),i}var he={application:null,Controller:null,Trix:null};function pe(n=he){let{application:e,Controller:t,Trix:i}=n;e.register("trix-embed",B({Controller:t,Trix:i}))}self.TrixEmbed={initialize:pe,generateKey:v,encryptValues:b,generateKeyAndEncryptValues:$};var qe=self.TrixEmbed;export{qe as default};
|
41
|
+
`};var je=[se,"a","abbr","acronym","address","b","big","blockquote","br","cite","code","dd","del","dfn","div","dl","dt","em","figcaption","figure","h1","h2","h3","h4","h5","h6","hr","i","iframe","img","ins","kbd","li","ol","p","pre","samp","small","span","strong","sub","sup","time","tt","ul","var"],He=["abbr","allow","allowfullscreen","allowpaymentrequest","alt","caption","cite","content-type","credentialless","csp","data-trix-embed","data-trix-embed-error","data-trix-embed-prohibited","data-trix-embed-warning","datetime","filename","filesize","height","href","lang","loading","name","presentation","previewable","referrerpolicy","sandbox","sgid","src","srcdoc","title","url","width","xml:lang"],k=class{constructor(e){this.controller=e,this.initializeTempates()}sanitize(e){let t=document.createElement("template");t.innerHTML=`<div>${e}</div>`;let n=t.content.firstElementChild;return[n].concat([...n.querySelectorAll("*")]).forEach(s=>{je.includes(s.tagName.toLowerCase())?[...s.attributes].forEach(a=>{He.includes(a.name.toLowerCase())||s.removeAttribute(a.name)}):s.remove()}),n.innerHTML}initializeTempates(){this.templates=V,Object.keys(V).forEach(e=>this.initializeTemplate(e))}initializeTemplate(e){var s,a;let t=`${e}TemplateValue`,n=this.controller[t],i=n?(a=(s=document.getElementById(n))==null?void 0:s.innerHTML)==null?void 0:a.trim():null;return this.controller[t]=null,i&&(this.templates[e]=i),this.templates[e]}render(e,t={}){return this.templates[e].replace(/{{(.*?)}}/g,(i,s)=>s.split(".").reduce((a,l)=>a[l],t))}renderEmbed(e="https://example.com"){let t=oe(e)?this.render("image",{src:e}):this.render("iframe",{src:e});return this.sanitize(t)}renderEmbeds(e=["https://example.com","https://test.com"]){if(e!=null&&e.length)return e.map(t=>this.renderEmbed(t))}renderWarnings(e=["https://example.com","https://test.com"],t=[],n=[]){if(!(e!=null&&e.length))return;t=[...t].sort(),t.includes("*")&&t.splice(t.indexOf("*"),1),n=[...n],n.includes("*")&&n.splice(n.indexOf("*"),1);let i=[...new Set([...n,...ee(e)])].sort();return this.render("warning",{header:"Copy/Paste Warning",subheader:"Content includes URLs or media from prohibited hosts or restricted protocols.",prohibited:{header:"Prohibited Hosts",hosts:i.length?i.map(s=>`<li>${s}</li>`).join(""):"<li>URLs and media are restricted to allowed hosts and standard protocols.</li>"},allowed:{header:"Allowed Hosts",hosts:t.length?t.map(s=>`<li>${s}</li>`).join(""):"<li>Allowed hosts not configured.</li>"}})}renderError(e){return this.render("error",{header:"Unhandled Exception!",subheader:"Report this problem to a software engineer.",error:e})}};function he(r={Controller:null,Trix:null}){var n;let{Controller:e,Trix:t}=r;return n=class extends e{connect(){this.onPaste=this.paste.bind(this),this.element.addEventListener("trix-paste",this.onPaste,!0),this.onBeforeFetchResponse=this.beforeFetchResponse.bind(this),addEventListener("turbo:before-fetch-response",this.onBeforeFetchResponse,!0),this.onBeforeUnload=this.forgetConfig.bind(this),addEventListener("beforeunload",this.onBeforeUnload,!0),this.store=new A(this),this.guard=new S(this),!this.key&&this.rememberConfig().then(()=>{this.paranoid&&this.guard.protect()})}reconnect(){let i=this.element.getAttribute("data-controller")||"",s=new Set(i.split(" "));s.add("trix-embed"),this.element.setAttribute("data-controller",[...s].join(" ").trim())}disconnect(){this.element.removeEventListener("trix-paste",this.onPaste,!0),removeEventListener("turbo:before-fetch-response",this.onBeforeFetchResponse,!0),removeEventListener("beforeunload",this.onBeforeUnload,!0),this.reconnect()}beforeFetchResponse(i){try{i.target.querySelectorAll("trix-editor").includes(this.element)&&this.forgetConfig()}catch(s){}}async paste(i){this.formElement&&(this.formElement.trixEmbedPasting=!0);try{let{html:s,string:a,range:l}=i.paste,o=s||a||"",d=this.createTemplateElement(o),c=te(d);if(!c.length)return;i.preventDefault(),this.editor.setSelectedRange(l);try{let m=new k(this),h=await this.allowedMediaHosts,u=await this.blockedMediaHosts,p=new Set(c.filter(g=>P(g)));[...d.querySelectorAll("iframe")].forEach(g=>p.add(g.src)),p=[...p];let y=p.filter(g=>C(g,h,u)),v=p.filter(g=>!y.includes(g)),W=await this.allowedLinkHosts,K=await this.blockedLinkHosts,$=c.filter(g=>!p.includes(g)),z=$.filter(g=>C(g,W,K)),q=$.filter(g=>!z.includes(g));if(v.length||q.length){let g=[...new Set([...v,...q])],pe=[...new Set([...h,...W])].filter(M=>!this.reservedDomains.includes(M)),fe=[...new Set([...u,...K])].filter(M=>!this.reservedDomains.includes(M));await this.insert(m.renderWarnings(g,pe,fe))}if(y.length&&await this.insert(m.renderEmbeds(y)),c.length===1&&y.length===1)return;let I=this.sanitizePastedElement(d,{renderer:m,validMediaURLs:y,validLinkURLs:z}).innerHTML.trim();I.length&&await this.insert(I,{disposition:"inline"})}catch(m){this.insert(renderer.renderError(m))}}finally{this.formElement&&delete this.formElement.trixEmbedPasting}}createTemplateElement(i){let s=document.createElement("template");return s.innerHTML=`<div>${i.trim()}</div>`,s.content.firstElementChild}extractLabelFromElement(i,s={default:null}){let a=i.title;return a&&a.length||(a=i.textContent.trim(),a&&a.length)?a:s.default}sanitizePastedElement(i,s={renderer:null,validMediaURLs:[],validLinkURLs:[]}){let{renderer:a,validMediaURLs:l,validLinkURLs:o}=s;i=i.cloneNode(!0);let d=O(i),c=[],m;for(;m=d.nextNode();)m.replacements=m.replacements||new Set,c.push(m),m.nodeValue.split(/\s+/).filter(p=>p.startsWith("http")).forEach(p=>{var v;let f=(v=b(p))==null?void 0:v.href,y=o.includes(f)||o.includes(f)?a.render("link",{url:f,label:f}):a.render("prohibited",{url:f,label:"Prohibited URL:",description:""});m.replacements.add({match:p,replacement:y})});return c.forEach(h=>{if(!h.replacements.size)return;let u=h.nodeValue;[...h.replacements].sort((f,y)=>y.match.length-f.match.length).forEach(f=>u=u.replaceAll(f.match,f.replacement)),h.replaceWith(this.createTemplateElement(u))}),i.querySelectorAll("a").forEach(h=>{let u=U(h),p=this.extractLabelFromElement(h,{default:u}),f=o.includes(u)?a.render("link",{url:u,label:p}):a.render("prohibited",{url:u,label:"Prohibited Link:",description:`(${p})`});h.replaceWith(this.createTemplateElement(f))}),i.querySelectorAll(ae.join(", ")).forEach(h=>{let u=U(h),p=this.extractLabelFromElement(h,{default:u}),f=l.includes(u)?a.render("embedded",{url:u,label:"Allowed Media:",description:"(Embedded Above)"}):a.render("prohibited",{url:u,label:"Prohibited Media:",description:""});h.replaceWith(this.createTemplateElement(f))}),i.innerHTML.replaceAll(/(\n|\r|\f|\v)+/g,"<br>"),i}createAttachment(i){return new t.Attachment({content:i,contentType:re.attachment})}insertNewlines(i=1,s={delay:1}){let{delay:a}=s;return new Promise(l=>{setTimeout(()=>{for(let o=0;o<i;o++)this.editor.insertLineBreak();l()},a)})}insertAttachment(i,s={delay:1}){let{delay:a}=s;return new Promise(l=>{setTimeout(()=>{this.editor.insertAttachment(this.createAttachment(i)),this.insertNewlines(1,{delay:a}).finally(l)},a)})}insertHTML(i,s={delay:1}){let{delay:a}=s;return new Promise(l=>{setTimeout(()=>{this.editor.insertHTML(i),this.insertNewlines(1,{delay:a}).finally(l)},a)})}insert(i,s={delay:1,disposition:"attachment"}){let{delay:a,disposition:l}=s;return i!=null&&i.length?new Promise(o=>{setTimeout(()=>{if(typeof i=="string")return l==="inline"?this.insertHTML(i,{delay:a}).catch(d=>this.renderError(d)).finally(o):this.insertAttachment(i,{delay:a}).catch(d=>this.renderError(d)).finally(o);if(Array.isArray(i)){let d=l==="inline"?i.map(c=>this.insertHTML(c,{delay:a+1})):i.map(c=>this.insertAttachment(c,{delay:a+1}));return Promise.all(d).catch(c=>this.renderError(c)).finally(o)}o()})}):Promise.resolve()}get editor(){return this.element.editor}get toolbarElement(){let i=this.element.getAttribute("toolbar"),s=i?document.getElementById(i):null;if(!s){let a=this.element.previousElementSibling;s=a!=null&&a.tagName.match(/trix-toolbar/i)?a:null}return s}get formElement(){return this.element.closest("form")}get inputElement(){var s;let i=this.element.getAttribute("input");return i?(s=this.formElement)==null?void 0:s.querySelector(`#${i}`):null}get paranoid(){return!!this.store.read("paranoid")}get key(){try{return JSON.parse(this.store.read("key"))[2]}catch(i){return null}}get hostsValueDescriptors(){return Object.values(this.valueDescriptorMap).filter(i=>i.name.endsWith("HostsValue"))}get reservedDomains(){return["embed.example","embed.invalid","embed.local","embed.localhost","embed.test","trix.embed.example","trix.embed.invalid","trix.embed.local","trix.embed.localhost","trix.embed.test","trix.example","trix.invalid","trix.local","trix.localhost","trix.test","www.embed.example","www.embed.invalid","www.embed.local","www.embed.localhost","www.embed.test","www.trix.example","www.trix.invalid","www.trix.local","www.trix.localhost","www.trix.test"]}rememberConfig(){return new Promise(async i=>{let s,a=await T();s=await x(a,w(this.reservedDomains,3)),this.store.write("key",JSON.stringify([s[0],s[1],a,s[2]])),this.paranoidValue!==!1&&(s=await x(a,w(this.reservedDomains,4)),this.store.write("paranoid",JSON.stringify(s))),this.element.removeAttribute("data-trix-embed-paranoid-value"),this.hostsValueDescriptors.forEach(async l=>{let{name:o}=l,d=o.slice(0,o.lastIndexOf("Value")),c=this[o];c.length<4&&(c=c.concat(w(this.reservedDomains,4-c.length))),this.store.write(d,JSON.stringify(await x(a,c))),this.hasOwnProperty(d)||Object.defineProperty(this,d,{get:async()=>{try{return(await X(this.key,JSON.parse(this.store.read(d)))).filter(h=>!this.reservedDomains.includes(h))}catch(m){return console.error(`Failed to get '${d}'!`,m),[]}}}),this.element.removeAttribute(`data-trix-embed-${l.key}`)}),s=await x(a,w(this.reservedDomains,4)),this.store.write("securityHosts",s),s=await x(a,w(this.reservedDomains,4)),this.store.write("obscurityHosts",s),i()})}forgetConfig(){var i,s,a,l;try{(i=this.store)==null||i.remove("key"),(s=this.store)==null||s.remove("paranoid"),this.hostsValueDescriptors.forEach(async o=>{var m;let{name:d}=o,c=d.slice(0,d.lastIndexOf("Value"));(m=this.store)==null||m.remove(c)}),(a=this.store)==null||a.remove("securityHosts"),(l=this.store)==null||l.remove("obscurityHosts")}catch(o){}}},J(n,"values",{embeddedTemplate:String,errorTemplate:String,iframeTemplate:String,imageTemplate:String,linkTemplate:String,prohibitedTemplate:String,warningTemplate:String,allowedLinkHosts:Array,blockedLinkHosts:Array,allowedMediaHosts:Array,blockedMediaHosts:Array,paranoid:{type:Boolean,default:!0}}),n}var ue=!1,Fe={application:null,Controller:null,Trix:null};function De(r=Fe){if(ue)return;let{application:e,Controller:t,Trix:n}=r;e.register("trix-embed",he({Controller:t,Trix:n})),ue=!0}self.TrixEmbed=L(E({},_),{encryptValues:x,generateKey:T,generateKeyAndEncryptValues:Q,initialize:De});var Tt=self.TrixEmbed;export{Tt as default};
|
@@ -1 +1 @@
|
|
1
|
-
{"inputs":{"app/javascript/encryption.js":{"bytes":4095,"imports":[{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"app/javascript/urls.js":{"bytes":
|
1
|
+
{"inputs":{"app/javascript/metadata.js":{"bytes":86,"imports":[],"format":"esm"},"app/javascript/encryption.js":{"bytes":4095,"imports":[{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"app/javascript/enumerable.js":{"bytes":517,"imports":[],"format":"esm"},"app/javascript/urls.js":{"bytes":3338,"imports":[],"format":"esm"},"app/javascript/media.js":{"bytes":3618,"imports":[{"path":"app/javascript/urls.js","kind":"import-statement","original":"./urls"}],"format":"esm"},"app/javascript/forms.js":{"bytes":3377,"imports":[{"path":"app/javascript/media.js","kind":"import-statement","original":"./media"},{"path":"app/javascript/urls.js","kind":"import-statement","original":"./urls"}],"format":"esm"},"app/javascript/guard.js":{"bytes":1211,"imports":[{"path":"app/javascript/forms.js","kind":"import-statement","original":"./forms"}],"format":"esm"},"app/javascript/store.js":{"bytes":1219,"imports":[{"path":"app/javascript/urls.js","kind":"import-statement","original":"./urls"}],"format":"esm"},"app/javascript/templates.js":{"bytes":1235,"imports":[],"format":"esm"},"app/javascript/renderer.js":{"bytes":5234,"imports":[{"path":"app/javascript/urls.js","kind":"import-statement","original":"./urls"},{"path":"app/javascript/media.js","kind":"import-statement","original":"./media"},{"path":"app/javascript/templates.js","kind":"import-statement","original":"./templates"}],"format":"esm"},"app/javascript/controller.js":{"bytes":16506,"imports":[{"path":"app/javascript/enumerable.js","kind":"import-statement","original":"./enumerable"},{"path":"app/javascript/encryption.js","kind":"import-statement","original":"./encryption"},{"path":"app/javascript/urls.js","kind":"import-statement","original":"./urls"},{"path":"app/javascript/media.js","kind":"import-statement","original":"./media"},{"path":"app/javascript/guard.js","kind":"import-statement","original":"./guard"},{"path":"app/javascript/store.js","kind":"import-statement","original":"./store"},{"path":"app/javascript/renderer.js","kind":"import-statement","original":"./renderer"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"},"app/javascript/index.js":{"bytes":669,"imports":[{"path":"app/javascript/metadata.js","kind":"import-statement","original":"./metadata"},{"path":"app/javascript/encryption.js","kind":"import-statement","original":"./encryption"},{"path":"app/javascript/controller.js","kind":"import-statement","original":"./controller"},{"path":"<runtime>","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"app/assets/builds/trix-embed.js":{"imports":[],"exports":["default"],"entryPoint":"app/javascript/index.js","inputs":{"app/javascript/metadata.js":{"bytesInOutput":24},"app/javascript/encryption.js":{"bytesInOutput":1346},"app/javascript/enumerable.js":{"bytesInOutput":226},"app/javascript/urls.js":{"bytesInOutput":1200},"app/javascript/media.js":{"bytesInOutput":935},"app/javascript/forms.js":{"bytesInOutput":1352},"app/javascript/guard.js":{"bytesInOutput":1002},"app/javascript/store.js":{"bytesInOutput":835},"app/javascript/templates.js":{"bytesInOutput":969},"app/javascript/renderer.js":{"bytesInOutput":2628},"app/javascript/controller.js":{"bytesInOutput":7934},"app/javascript/index.js":{"bytesInOutput":311}},"bytes":19276}}}
|