Advice on how to use certain packages. E.g. Medium Editor


#1

Disclaimer - noobie trying to get my head round things, so this is probably a very basic question.

Using: Meteor + React


All the tutorials/videos etc I have read/seen import something from one component to another (makes sense). But reading the documentation of certain packages, there is no reference to import/what to import. I understand how to translate var xyz = require(‘xyz’) into the correct import statements, but sometimes that is missing as well.

So, working with an actual example - how would I go about using this in my app:
https://atmospherejs.com/mediumeditor/mediumeditor -

…or any of the ‘medium’ style editors out there:
https://atmospherejs.com/?q=medium

Thanks in advance!


#2

So this is what I would currently do to find out what I need to specify in the import statement (xxx below) for an atmosphere package:

import { xxx } from 'meteor/some:package';

Check the README or docs. That didn’t help for this package! But I did see that I could do a meteor add mediumeditor:mediumeditor. More on that later!

Next, I would normally look at the api.export statement(s) in the package.js file in the github repo. Unfortunately, the repo has no package.js. The README uses the npm install command, which for Meteor I would replace with meteor npm install medium-editor --save.

In the case of npm packages I refer to the package docs for the details: if I see var Something = require('packagename');, I may either use the require syntax, or replace with import Something from 'packagename'; (no braces around the variable), which I think you are already comfortable with.

Unfortunately (again), in the case of this package, the instructions require you to add script tags to your page, which led me to conclude that it’s going to define (a) global variable(s) itself. Packages like this don’t always fit into import syntax and you will need to follow ancient rituals to add them to meteor. If you’re interested in doing this (and you should read to the end first!), you should install the package, copy the script file from the appropriate node_modules folder into a client/compatibility/ folder within your project.

meteor npm install medium-editor --save
mkdir client/compatibility
cp node_modules/medium-editor/dist/js/medium-editor.min.js client/compatibility

That should expose MediumEditor globally.

However, this package piqued my curiosity, so I did a meteor add mediumeditor:mediumeditor and then looked at the code which was brought into the cache to see what was going on and I discovered a reference to Meteor’s file-scoped variables and exposing a global MediumEditor object. That is pretty normal for what I’d expect to see, so I added this to my client/main.js:

import { MediumEditor } from 'meteor/mediumeditor:mediumeditor';

and it worked! :slight_smile:


#3

Just adding one more “trick” to @robfallows great breakdown. After you’ve added the package to your app (via meteor add mediumeditor:mediumeditor), open your app in a browser and dump the Package global in your developer console. This will list all available packages and their exports. You can then use this to wire up your import. For example:

becomes:

import { MediumEditor } from 'meteor/mediumeditor:mediumeditor';

#4

Oh nice trick @hwillson! :slight_smile:


#5

Legends both of you!

Will go try and put it all into practice right-away…


#6

RIghto - Was offline for a couple of days after a 30 hour flight. Got a chance to give this a crack, but haven’t had a chance to post feedback up here:

@hwillson - love the Packages tip. Really helped make sure I am installing things all correctly (beyond just this package).

@robfallows
Import worked to get the code into my file :smiley: I was struggling to actually use it though. I went ahead and looked for the code you saw that tipped you off about the import statement (to see if that threw off any tips) but when I try and make use of the code (e.g. making a textarea with the editor funcionality), I keep getting an error:

‘mediumeditor_mediumeditor.js?hash=d21a801…:5019Uncaught TypeError: Cannot read property ‘init’ of undefined’

I’ve gone through the package code to try and debug and found the bit that I think is causing the problem:

function MediumEditor(elements, options) {                                                                             // 4981
    'use strict';                                                                                                      // 4982
    return this.init(elements, options);                                                                               // 4983
}   

So from what I gather, the imported MediumEditor is unable to read from the below piece of code in the main package on line 1596:

Extension.prototype = {                                                                                            // 1588
        /* init: [function]                                                                                            // 1589
         *                                                                                                             // 1590
         * Called by MediumEditor during initialization.                                                               // 1591
         * The .base property will already have been set to                                                            // 1592
         * current instance of MediumEditor when this is called.                                                       // 1593
         * All helper methods will exist as well                                                                       // 1594
         */                                                                                                            // 1595
        init: function () {},       

That is what I suspect anyway but I am unsure how to fix it. Would it be that I have to import the whole module beyond just { MediumEditor } or have I missed something simple/obvious?

:confused: I’ll keep chipping away at it but thanks in advance for any other pointers!


#7

So I’ve just done a quick test.

meteor create mediumtest
cd mediumtest
meteor npm i
meteor add mediumeditor:mediumeditor

client/main.html

<head>
  <title>mediumtest</title>
</head>

<body>
  {{> hello}}
</body>

<template name="hello">
  <div class="editable"></div>
</template>

client/main.js

import { Template } from 'meteor/templating';
import { MediumEditor } from 'meteor/mediumeditor:mediumeditor';

import './main.html';

Template.hello.onRendered(function() {
  // const editor = new MediumEditor(document.querySelectorAll('.editable'));
  const editor = new MediumEditor('.editable');
});

That seems to work.

EDIT: Forgot the meteor add mediumeditor:mediumeditor.


#8

Yup that did it! Thank you so much @robfallows

Code, translated to React below (for reference in case anyone else finds this useful):

class Body extends Component {

    componentDidMount() {
        const editor = new MediumEditor('.editable');
    }

    render() {
        return (
            <div className="editable">
            </div>
        );
    }
}

export default Body;