Incorporating Unique Typography with Typekit/Adobe Fonts in Tiny MCE editor within a React

I'm currently working on integrating a custom Adobe Typekit font into a TinyMCE React component to customize the text styling within the editor. Here is the setup I have:

<Editor
        init={{
          allow_html_in_named_anchor: false,
          branding: false,
          plugins: [
            "autolink lists link image preview anchor",
            "searchreplace",
            "insertdatetime media table paste code"
          ],
          toolbar: "bold italic | bullist numlist",
          content_css: ["https://use.typekit.net/XXXXXX.css", "/overrides.css"]
        }}
      />

To maintain privacy, I have redacted the Typekit CSS filename, as it is specific to each user account.

The overrides.css file is structured as follows:

@import url("https://use.typekit.net/XXXXX.css");
body {
  font-family: "neue-haas-grotesk-text, Arial, sans-serif" !important;
  font-size: 14px;
  font-weight: 400;
}

Within the <head> tag of the TinyMCE editor-generated <iframe>, there are two CSS <link> tags present in the correct sequence:

<link rel="stylesheet" type="text/css" id="mce-u0" crossorigin="anonymous" referrerpolicy="origin" href="https://cdn.tiny.cloud/1/k9s4r4mdxeukqc7mrign93b26zofvznzyw98lj16y5rlb73z/tinymce/5.10.3-128/skins/ui/oxide/content.min.css">

<link rel="stylesheet" type="text/css" id="mce-u1" crossorigin="anonymous" referrerpolicy="origin" href="https://use.typekit.net/XXXXXX.css">

<link rel="stylesheet" type="text/css" id="mce-u0" crossorigin="anonymous" referrerpolicy="origin" href="https://cdn.tiny.cloud/1/k9s4r4mdxeukqc7mrign93b26zofvznzyw98lj16y5rlb73z/tinymce/5.10.3-128/skins/ui/oxide/content.min.css">

I have attempted to import the CSS file twice, once in the overrides.css and once in the content_css property. However, I am facing issues as the editor displays a bizarre serif font, not even the specified Arial or default 'sans-serif'.

Although the CSS stylesheets load correctly and the Adobe font is functioning on the page where the editor is placed, it does not reflect within the editor preview itself.

Answer №1

To implement the necessary functionality, you will have to develop a custom plugin to handle it. Initially, we will initialize the plugin using the following code:

tinymce.PluginManager.add( 'typekit', function( editor ) {}

Within the plugin, we need to define a function that will insert a script responsible for loading the required fonts:

function addScriptToHead() {}

Next, we will access the DOM object within the function:

var doc = editor.getDoc();

Generate a script that will be added to the header:

var jscript = "(function() {\n\
            var config = {\n\
                kitId: 'xxxxxxx'\n\
            };\n\
            var d = false;\n\
            var tk = document.createElement('script');\n\
            tk.src = '//use.typekit.net/' + config.kitId + '.js';\n\
            tk.type = 'text/javascript';\n\
            tk.async = 'true';\n\
            tk.onload = tk.onreadystatechange = function() {\n\
                var rs = this.readyState;\n\
                if (d || rs && rs != 'complete' && rs != 'loaded') return;\n\
                d = true;\n\
                try { Typekit.load(config); } catch (e) {}\n\
            };\n\
            var s = document.getElementsByTagName('script')[0];\n\
            s.parentNode.insertBefore(tk, s);\n\
        })();";

Include the font script:

var script = doc.createElement( 'script' );
script.type = 'text/javascript';
script.appendChild( doc.createTextNode( jscript ) );

Add the script to the header:

doc.getElementsByTagName( 'head' )[0].appendChild( script );

Invoke our function:

editor.onPreInit.add( function( editor ) {
            addScriptToHead();
        });

The complete code snippet:

tinymce.PluginManager.add( 'typekit', function( editor ) {
    function addScriptToHead() {
            var doc = editor.getDoc(); // gets dom element from iframe
            var jscript = "(function() {\n\
                var config = {\n\
                kitId: 'xxxxxxx'\n\
            };\n\
            var d = false;\n\
            var tk = document.createElement('script');\n\
            tk.src = '//use.typekit.net/' + config.kitId + '.js';\n\
            tk.type = 'text/javascript';\n\
            tk.async = 'true';\n\
            tk.onload = tk.onreadystatechange = function() {\n\
                var rs = this.readyState;\n\
                if (d || rs && rs != 'complete' && rs != 'loaded') return;\n\
                d = true;\n\
                try { Typekit.load(config); } catch (e) {}\n\
            };\n\
            var s = document.getElementsByTagName('script')[0];\n\
            s.parentNode.insertBefore(tk, s);\n\
        })();";

    var script = doc.createElement( 'script' );
    script.type = 'text/javascript';
    script.appendChild( doc.createTextNode( jscript ) );

    // Add the script to the header
    doc.getElementsByTagName( 'head' )[0].appendChild( script );
}
editor.onPreInit.add( function( editor ) {
            addScriptToHead();
        });

The idea behind this solution is something I implemented in my code a while ago, although I can't recall its exact origin.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Altering the display attribute cancels out any opacity transitions

When using JavaScript to change the opacity of an element with transition: opacity 1s, the expected duration of one second is met, as demonstrated here: onload = e => { var p = document.getElementsByTagName("p")[0]; p.style.opacity = 1; }; p { ...

Achieve SEO excellence with Angular 4 in production settings

I am currently building a website using Angular 4 as part of my personal study project. Although my website is live, I realized that it's not SEO friendly. After making some changes, I came across a valuable resource on server-side rendering in Angul ...

Adjust the background color of Bootstrap 4 checkboxes

I'm trying to figure out how I can modify the background color of a Bootstrap 4 checkbox in this specific scenario. .custom-control-label::before, .custom-control-label::after { top: .8rem; width: 1.25rem; height: 1.25rem; } <link rel="style ...

The NEXT.js API endpoint is not configured to handle POST requests

I am having an issue with my Next.js API route located at "pages/api/contact". The API appears to be working when I process a GET request or navigate to localhost:3000/api/contact. However, when attempting to process a POST request to this API ro ...

When deploying projects that are set up with Vercel or Next.js, the rewriting process may encounter difficulties in locating the assets path

I am implementing a structure that allows one domain to serve multiple projects: There is a repository containing a vercel.json file that configures paths to other projects Another repository contains a sample home app And yet another repository contains ...

The header component constantly refreshes upon switching routes in a React application

When clicking on the {Link} and changing the Route, the header component NavBar continues to re-render, even though it is located outside the Switch component from react-router-dom. Here are the relevant files: Main index.js file: import React from &a ...

Is there a way to set up a linked component's peerDependencies to utilize the corresponding node_modules of the linked script?

I am currently utilizing npm version 3, which is pertinent due to the changes in the behavior of peerDependencies in this version. In my project, I have a reactjs app named "game" along with a reactjs component named "player". The "game" app is being run u ...

Display additional links in Bootstrap navigation bar with a second level menu

Currently, I am integrating Bootstrap into an ASP.NET application using C#. Within this application, I have implemented a two-level menu system where certain options are available to users and others are only visible to administrators. The decision on whic ...

What is the best method to create a gap between the header and table body in Angular Material version 13?

Is there a way to create space (margin) between the header and body in an Angular Material table? I initially attempted to use a solution found here, but it was unsuccessful. Check out the demo here: https://stackblitz.com/edit/angular-ivy-anphrw?file=sr ...

Unit testing in Jest using Luxon: Is there a way to mock the .setZone('local') function?

I have a straightforward date component that I've been working on: import { DateTime } from 'luxon'; export const DateComponent = ({ item, itemKey }) => { const isoDateString = item[itemKey]; if (!isoDateString) { return ...

Adding npm packages to your Vue.js application

My Vue app is structured like this (auto created by vue init webpack myProject): index.html components/ -main.js -App.vue I am trying to include npm packages, such as https://github.com/ACollectionOfAtoms/atomic-bohr-model. Following the instructions, I ...

What could be the reason for the failure of Angular Material Table 2 selection model?

A Question about Angular Mat Table 2 Selection Model Why does the selection model in Angular Mat Table 2 fail when using a duplicate object with its select() or toggle() methods? Sharing Debugging Insights : Delve into my debugging process to understand ...

Having trouble adding a property to an object, any solutions?

I've been struggling with adding a property to a nested Object in my JavaScript code. Despite setting the property name and value, the property doesn't seem to persist. populated_post.comments[i].comment.end = true console.log(typeof(populated_po ...

Refreshing the access token in Linkedin's oauth does not result in extending the expiration time

Currently, I am implementing a strategy to renew Linkedin OAuth2 access tokens. When starting the OAuth process in the browser, the dialogue is skipped and a new code is generated. This code is then used to acquire a fresh access_token that differs from t ...

Sending Dual Parameters to PHP File Using AJAX

Currently, I am facing an issue where I can successfully pass one value to a Bootstrap modal via AJAX, but my code stops working when I try to pass a second value. JavaScript function claimOrder(str, stre){ if (str=="") { document.getElementById("txtH"). ...

Encountered an issue with md-autocomplete: Attempting to read property 'success' of an undefined element

I encountered an issue while using Material Angular framework and md-autocomplete. The error message I receive is: Cannot read property 'success' of undefined. Below is the snippet of my code: /*My app.js*/ var app = angular.module('app&apo ...

Generating a fresh object derived from an existing object without saving any modifications

I am facing an issue with using an Array to store boilerplate objects that can be copied, modified, and added to another Array. The problem arises when the new Array takes ownership of the object, causing changes to persist in the original object. For exa ...

Transforming numbers into arrays in JavaScript/TypeScript for Angular 7

What is the best way to convert the number 10 into an array in JavaScript? expected output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] OR How can I transform the number 10 into the number of items within an array using JavaScript? ...

Vue.js is unable to render the template using Object

During this demonstration at https://jsfiddle.net/ccforward/fa35a2cc/, I encountered an issue where the template could not render and the data in resultWrong remained empty with a value of {} At https://jsfiddle.net/ccforward/zoo6xzc ...

Link inserted in between spaces

Working with Eloqua. Any ideas on what might be causing a space to appear in a link? The space doesn't show up during testing, only in the live version. Here is the code snippet: <p style="line-height:18px;"> <font face="calibri, Arial, H ...