Installations
npm install ember-froala-editor
Developer Guide
Typescript
No
Module System
N/A
Min. Node Version
>= 18
Node Version
20.9.0
NPM Version
10.1.0
Score
45
Supply Chain
54.6
Quality
78.8
Maintenance
100
Vulnerability
94.9
License
Releases
Contributors
Unable to fetch Contributors
Languages
JavaScript (95.92%)
HTML (2.91%)
Handlebars (0.98%)
CSS (0.19%)
Developer
Download Statistics
Total Downloads
1,883,710
Last Day
21
Last Week
3,437
Last Month
29,464
Last Year
353,000
GitHub Statistics
70 Stars
519 Commits
35 Forks
8 Watching
5 Branches
19 Contributors
Package Meta Information
Latest Version
4.3.1
Package Id
ember-froala-editor@4.3.1
Unpacked Size
51.12 kB
Size
15.94 kB
File Count
25
NPM Version
10.1.0
Node Version
20.9.0
Publised On
19 Nov 2024
Total Downloads
Cumulative downloads
Total Downloads
1,883,710
Last day
-98.5%
21
Compared to previous day
Last week
-59.1%
3,437
Compared to previous week
Last month
-12.2%
29,464
Compared to previous month
Last year
8.1%
353,000
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
Dependencies
8
Peer Dependencies
1
Dev Dependencies
36
ember-froala-editor
Bring the Froala WYSIWYG Editor into an ember-cli project with this addon. Besides importing the required Froala Editor files, the main part of this addon is the
<FroalaEditor />
component, which adds the editor in your ember app. Other functionality is also included to help interact with the editor and content, see the Usage section below.
Compatibility
- Ember.js v3.20 or above
- Ember CLI v3.20 or above
- Node.js v18 and above
ember-auto-import
v2 or above
Note on ember-auto-import
version requirement
This addon (and Ember v4+) uses ember-auto-import
v2, which implies that
consuming projects also use ember-auto-import
v2. Outside of
npm install --save-dev ember-auto-import@^2.0.0 webpack
, take a look at the
upgrade guide
for further details when upgrading from ember-auto-import
v1.
Upgrading from 3.x
The only change is with the configuration options in ember-cli-build.js
. All
option types (languages, plugins, themes) must now be arrays with specific
assets listed. Boolean and string values are no longer supported. Ex:
From
1let app = new EmberApp(defaults, {
2 'ember-froala-editor': {
3 languages: 'es',
4 plugins : ['align','char_counter'],
5 themes : true
6 }
7});
To
1let app = new EmberApp(defaults, { 2 'ember-froala-editor': { 3 languages: ['es'], 4 plugins : ['align','char_counter'], 5 themes : ['dark','gray','royal'] 6 } 7});
No other changes needed from an ember perspective. Installation and usage is still the same, but editor configuration options might have changed. See the Froala Editor docs for those details.
Installation
ember install ember-froala-editor
Configuration
This addon will import files from the froala-editor
package into the build-tree
to be included in the final app output. This covers the Download details
on the Froala Editor docs to get the main editor files into your project. You
can additionally include languages, plugins, and themes by
adding configuration details in your ember-cli-build.js
file.
Within the ember-cli-build.js
file, add a ember-froala-editor
object and
list which additional assets to include in an array. For plugins, you can use
either the plugin name as shown in the Froala Editor docs or file name (without
the extension). Ex:
1// ember-cli-build.js 2// ... (snip) 3let app = new EmberApp(defaults, { 4 'ember-froala-editor': { 5 languages: ['es','fr','de'], 6 plugins : ['align','charCounter','paragraph_format'], 7 themes : ['royal'] 8 } 9}); 10// ... (snip)
Usage
This addon includes a couple components, several template helpers, and a couple test helpers.
<FroalaEditor>
Component
The <FroalaEditor>
component exposes many aspects of the Froala Editor in
"Ember ways" and uses the <div contenteditable>
version of the editor (not
<textarea>
). And with the Froala Editor being a third-party program, this
component will handle proper setup and teardown.
1<FroalaEditor />
Pass-in existing HTML/content via the @content
argument and capture changes
from the @update
argument (which should be a setter, including {{mut}}
).
However, when using {{mut}}
it must be wrapped in {{fn}}
to retain the
function (setter) aspect. The @content
must be a SafeString from
htmlSafe
and @update
will also return a SafeString.
1<FroalaEditor 2 @content={{this.content}} 3 @update={{fn (mut this.content)}} 4/>
The @update
setter will be called on the contentChanged
editor event
by default. There is a slight debounce effect with that event, which may or
may not be desirable. To change which event is used, pass in the event name
through the @updateEvent
argument.
1<FroalaEditor 2 @content={{this.content}} 3 @update={{fn (mut this.content)}} 4 @updateEvent="input" 5/>
Options can be passed in through the @options
argument or individually
using the option name as the @argument
name. Note: If the same option is
passed within the @options
argument and individual argument, the individual
argument will "win". In the example below, the theme would be "dark".
1<FroalaEditor 2 @options={{hash theme="gray"}} 3 @theme="dark" 4/>
Event callbacks can be passed into the component using the @on-*
argument
format, where the event name is prefixed with @on-
. Also, when an event has a
period in the name, replace it with a dash. The callback will be given the editor
instance as the first argument, with the other event params (if any) following.
1<FroalaEditor 2 @on-focus={{this.focusCallback}} 3 @on-paste-afterCleanup={{this.pasteCallback}} 4 @on-commands-after={{this.commandsCallback}} 5/>
The callback signatures should look like;
1function(editor, ...params) {}
2// Or for the examples above
3function focusCallback(editor) {}
4function pasteCallback(editor, clipboard_html) {}
5function commandsCallback(editor, cmd, param1, param2) {}
The <FroalaEditor>
also watches the @disabled
state and will appropriately
enable/disable the editing abilities when this argument changes. It basically
is the equivalent to the <textarea disabled>
attribute.
1<FroalaEditor 2 @disabled={{this.disabled}} 3 @on-edit-on={{this.editorEnabledCallback}} 4 @on-edit-off={{this.editorDisabledCallback}} 5/>
<FroalaContent>
Component
According to the Froala Editor documentation, content created from the
editor should be contained within an element with the .fr-view
class. This
is simply a component that applies the class. It can be used in either inline
(with the @content
argument) or block form, but either should be SafeString
from the htmlSafe()
.
1{{!-- this.content = htmlSafe('<p>Content here</p>') --}} 2<FroalaContent @content={{this.content}} /> 3<FroalaContent>{{this.content}}</FroalaContent>
Either will render:
1<div class="fr-view"><p>Content here</p></div>
{{froala-arg}}
Template Helper
This helper creates a closure that will capture the editor instance and pass it
into the event callback as the first argument, with the other event args
following. The Froala Editor binds callbacks to the editor instance, so this
is the editor and not the original context (even with the @action
decorator).
Note: All @on-*
arguments on the <FroalaEditor>
already have this applied
automatically. This is mainly useful when passing callbacks through the
events
option.
1<FroalaEditor 2 @options={{hash events=(hash click=(froala-arg this.callback))}} 3 @on-click={{this.callback}} 4/>
The callback signature should look like;
1function(editor, ...args) {}
2// Or for the example above with the click event
3function(editor, clickEvent) {}
{{froala-html}}
Template Helper
This helper creates a closure that will pass the editors current HTML/content
as the first argument to the callback function. This is very useful when
combined with setters or the {{mut}}
helper.
Ex: {{froala-html (fn (mut this.content))}}
Note: The @update
argument on <FroalaEditor>
already has this applied
automatically. This is mainly useful when needing HTML on other callbacks
but can also be done by calling editor.html.get()
from within your callback.
1<FroalaEditor 2 @options={{hash events=(hash input=(froala-html this.callback))}} 3 @on-input={{froala-html this.callback}} 4/>
The callback signature should look like;
1function(html, editor, ...args) {}
2// Or for the example above with the input event
3function(html, editor, inputEvent) {}
{{froala-method}}
Template Helper
This helper creates a closure that will call an editor method when
called. It is meant to replace an event callback on the
<FroalaEditor>
component. Simply specify the method name as the
first parameter of the helper.
1<FroalaEditor 2 @on-paste-after={{froala-method "commands.undo"}} 3/>
The helpers first parameter will be used as the editor method to be called, and the remaining parameters will be used for method arguments. So you can pass in the proper arguments as documented, and they will be spread out when called. Ex:
1{{froala-method "align.apply" "right"}}
In addition, you can use values from the event callback and "proxy" them to the method. First, define a parameter in the position which the argument should be passed in (to). Then define a hash with the same name and an integer of the position (1 indexed) which the argument would have been received (from). Ex:
1<FroalaEditor 2 @on-save-error={{froala-method "html.insert" "message" message=2}} 3/>
In the above example, the "on-save-error" event callback would have received
(editor, error)
. In the {{froala-method}}
helper we defined a "message"
and told it to use the second argument, which is error
.
{{html-safe}}
Template Helper
Since the <FroalaEditor>
requires that @content
be a SafeString from
htmlSafe()
, this helper can provide a way to convert a content string
when passing to the editor component. However, you should also sanitize the
content going in to guard against XSS exploits.
Note: This helper is NOT automatically imported into the app. Rather, you must create your own helper to re-export the helper from this addon.
ember generate helper html-safe
- Change
app/helpers/html-safe.js
toexport { default } from 'ember-froala-editor/helpers/html-safe';
- Use
{{html-safe}}
in your app templates
1<FroalaEditor 2 @content={{html-safe this.content}} 3/>
{{to-string}}
Template Helper
Since the <FroalaEditor>
requires that @content
to be a SafeString, it will
also return a SafeString from the @update
callback (and any callbacks that
use the {{froala-html}}
helper). This helper will convert that SafeString
back to a normal string. However, you should also sanitize the content coming
back to guard against XSS exploits.
Note: This helper is NOT automatically imported into the app. Rather, you must create your own helper to re-export the helper from this addon.
ember generate helper to-string
- Change
app/helpers/to-string.js
toexport { default } from 'ember-froala-editor/helpers/to-string';
- Use
{{to-string}}
in your app templates
1<FroalaEditor 2 @content={{html-safe this.content}} 3 @update={{to-string (fn (mut this.content))}} 4/>
{{merged-hash}}
Template Helper
This helper is a little out-of-scope for this addon, but can be very useful
when you need to use a combination of options
. It allows you to use an
object / hash property but also add others or override options. Ex:
1<FroalaEditor 2 @options={{merged-hash this.parentOptions heightMin=400}} 3/>
The helper assumes all parameters are objects, and then uses assign() to merge everything together. Each parameter takes priority on the previous, with the "hash" (named parameters) being the final. So you can merge multiple "levels" of options. Ex:
1{{merged-hash 2 this.applicationOptions 3 this.routeOptions 4 pastePlain=true 5 placeholderText="Only plain text can go here..."}}
Note: This helper is NOT automatically imported into the app. Rather, you must create your own helper to re-export the helper from this addon.
ember generate helper merged-hash
- Change
app/helpers/merged-hash.js
toexport { default } from 'ember-froala-editor/helpers/merged-hash';
- Use
{{merged-hash}}
in your app templates
fillInFroalaEditor()
Test Helper
Test helper to best simulate content within the editor changing. It uses the
fillIn()
helper provided by ember-test-helpers
but just ensures the
correct DOM element is targeted. It requires a selector (string) as the first
argument and HTML (string or SafeString) as the second argument. As an
async function, you should await
the results before continuing with your test.
1import { fillInFroalaEditor } from 'ember-froala-editor/test-support'; 2await fillInFroalaEditor('#editorId', '<p>HTML</p>');
getInFroalaEditor()
Test Helper
Test helper that grabs the innerHTML
of the editor content, simple as that.
It returns the HTML as a string and not a SafeString, unlike {{froala-html}}
.
1import { getInFroalaEditor } from 'ember-froala-editor/test-support'; 2let content = getInFroalaEditor('#editorId');
So putting both of these test helpers together, an Acceptance Test might look something like this;
1import { module, test } from 'qunit'; 2import { visit } from '@ember/test-helpers'; 3import { setupApplicationTest } from 'ember-qunit'; 4import { fillInFroalaEditor, getInFroalaEditor } from 'ember-froala-editor/test-support'; 5 6module('Acceptance | FroalaEditor', function(hooks) { 7 setupApplicationTest(hooks); 8 9 test('<FroalaEditor> properly updates when content is filled in', async function(assert) { 10 assert.expect(2); 11 12 await visit('/'); 13 assert.strictEqual(getInFroalaEditor('#editor'), '<p>Foobar</p>'); 14 15 await fillInFroalaEditor('#editor', '<p>Foobaz</p>'); 16 assert.strictEqual(getInFroalaEditor('#editor'), '<p>Foobaz</p>'); 17 }); 18});
Defaults for <FroalaEditor>
component
Most likely you will have customizations/options that are common across many/all
of your <FroalaEditor>
instances. Instead of passing around a shared options
object, there are a few ways to apply "default" options at once. And both ways
can be applied at the same time (ex: environment.js
for the key and extending
for options/callbacks).
environment.js
config
The <FroalaEditor>
first looks to your config/environment.js
file for a
ember-froala-editor
object to use as the options
. This is a great
place for your key after purchasing the Froala Editor.
1'use strict'; 2 3module.exports = function(environment) { 4 var ENV = { 5 // (other default code snipped...) 6 7 'ember-froala-editor': { 8 key: '_YOUR_KEY_HERE_' 9 } 10 11 }; 12 // ... (other default code snipped...) 13 return ENV; 14};
Extending <FroalaEditor>
component
The <FroalaEditor>
was created with extending and applying defaults in mind.
Simply generate a new component within your app, extending from the addons
component and apply options and event callbacks, similar to invoking
the editor in a template by passing arguments, but instead make them class
properties and methods.
ember generate component-class froala-editor
- Change
app/components/froala-editor.js
to the example show below, where the editor is extended - Add options to the
options = {}
object or individually - Add event callbacks with the
on-eventName
naming strategy
- Note: Use the
@action
decorator to retain the component context
1// app/components/froala-editor.js 2import FroalaEditorComponent from 'ember-froala-editor/components/froala-editor'; 3 4export default class FroalaEditor extends FroalaEditorComponent { 5 options = { 6 theme: "gray" 7 }; 8 // OR 9 theme = "gray"; 10 11 'on-eventName'(editor, ...args) {/* this = editor */} 12 @action 'on-eventName'(editor, ...args) {/* this = component */} 13}
Custom Elements
The Froala Editor allows the creation of custom elements to use within the editor, such as custom buttons, dropdowns, popups, icons, and plugins. These should be created from within an application initializer so they are created/setup just once. Then you can use them within the editor as shown in the Froala Editor docs.
ember generate initializer froala-editor-elements
-- Or name(s) of your choosingimport FroalaEditor from 'froala-editor';
FroalaEditor.DefineIcon()
,FroalaEditor.RegisterCommand()
, etc.
1import FroalaEditor from 'froala-editor'; 2 3export function initialize(/* application */) { 4 FroalaEditor.RegisterCommand('myButton', {}); 5} 6 7export default { 8 initialize 9};
FAQ
Why can't I use the {{on}}
modifier for Froala Editor events?
Starting with Froala Editor v3, it no longer triggers custom events on the DOM.
Instead, the new way is to pass callbacks into the options.events
object,
or use the editor.events.on()
method. This is done for you with the
<FroalaEditor />
component by taking all @on-*
args and adding them
to the editor using the editor.events.on()
method.
Why can't I customize the editor tagName
?
With the move to Glimmer Components, the tagName
is no longer customized
through the component class. Rather, the forthcoming(?) (element)
helper
will fill this need but it is not released in Ember.js proper yet. Once it is,
you'll be able to customize the emitted DOM Element using the @tagName
argument.
Just to note, the Froala Editor itself modifies the DOM quite a bit, so the
emitted element might change anyway.
Why can't content be passed into <FroalaEditor>
in block form?
Content changes must be captured by the component to properly update the editor
using editor.html.set()
instead of through the Glimmer template. When content
is passed in via block form (<FroalaEditor>{{this.content}}</FroalaEditor>
)
there is no way for the Glimmer component class to capture updates.
Is there a way to enable two-way binding of @content
?
As of this writing, no. Ember Octane with Glimmer Components do not allow
two-way bound @arguments
whatsoever. However, there has been discussion
on how to explicitly enable two-way binding in some manor, possibly by
a "boxing" a value with a setter. The <FroalaEditor>
was designed with
this in mind, where the @update
argument could look for a setter on
@content
, without needing to pass in the setter explicitly/separately.
Why can't @content
be a regular string anymore?
There has been some debate on if the <FroalaEditor>
itself should automatically
display @content
unescaped by applying htmlSafe()
. Rather, the user
of the component should indicate that the @content
is Ok to display in its'
current form. Additionally, by requiring a SafeString, the addon was able to
allow greater backwards compatibility without resorting to computeds. We can
always go back on this decision but it was a good change to make at v3.
Why is my build output size larger with v4?
With the move to ember-auto-import
, all possible dynamic import()
assets
are included in the build. Therefore, all language files, plugins, and themes
will be included in the project build output. However, only those listed in
your ember-cli-build.js
ember-froala-editor
options will actually be
requested by your browser.
Why is it recommended to depend upon a minor version and not major?
Ex: ~4.0.0
instead of ^4.0.0
. Froala would like this addon (and other
official integrations) to match versions of the main editor package.
While we try to withold breaking changes to a major release, there are times
where changes in the Ember ecosystem require changes to the addon, before the
next major release of the Froala Editor (we note these in the release notes).
Contributing
See the Contributing guide for details.
License
The ember-froala-editor
project is under MIT License. However, in
order to use Froala WYSIWYG HTML Editor plugin you must purchase a license for it.
Froala Editor has 3 different licenses for commercial use. For details please see License Agreement.
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
12 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE.md:0
- Info: FSF or OSI recognized license: MIT License: LICENSE.md:0
Reason
Found 0/17 approved changesets -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/ci.yml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:36: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:65: update your workflow using https://app.stepsecurity.io/secureworkflow/froala/ember-froala-editor/ci.yml/master?enable=pin
- Info: 0 out of 3 GitHub-owned GitHubAction dependencies pinned
- Info: 0 out of 3 third-party GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 14 are checked with a SAST tool
Reason
16 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-whgm-jr23-g3j9
- Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx
- Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97
- Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp
- Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j
- Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w
- Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg
- Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p
- Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36
- Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q
Score
3.4
/10
Last Scanned on 2024-12-23
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More