ember-remarkable icon indicating copy to clipboard operation
ember-remarkable copied to clipboard

Dynamic text not working on ember-cli 2.8

Open milindalvares opened this issue 8 years ago • 11 comments

{{md-text
            text = "{{link-to 'index' 'index'}}"
            dynamic=true
          }}

Works fine without the dynamic flag. No error in console or anything, just a blank page.

milindalvares avatar Sep 26 '16 08:09 milindalvares

Error in console while trying to use dynamic=true in ember-cli > 2.6:

_ember['default'].HTMLBars.compile is not a function

They for some reason removed .compile from HTMLBars. I tried looking for solution, but couldn't find any. I'll gladly provide a pull request if anyone can point me in the right direction.

maciek134 avatar Dec 02 '16 12:12 maciek134

Hello, I have found this useful answer on StackOverflow: https://stackoverflow.com/questions/37345098/dynamically-compile-a-htmlbars-template-at-runtime-in-ember-2-5 May be helpful; sure, at this point it will require more NPM dependencies, but I think it's worth the effort if it gives dynamic template compile from ember-remarkable.

danieledraganti avatar Jun 13 '17 11:06 danieledraganti

By adding app.import('vendor/ember/ember-template-compiler.js'); on ember-cli-builld.js it worked (taken from the link pasted above), so I think we should close this issue @johnotander

vasilakisfil avatar Dec 12 '17 18:12 vasilakisfil

I'm having similar problems with ember 3.1 with Error: Cannot call compile without the template compiler loaded. Please load ember-template-compiler.js prior to calling compile. How? ember-template-compiler.js now lives at ember-source/dist/ember-template-compiler.js but I don't know how to use it in my module.

buzzware avatar May 10 '18 14:05 buzzware

@buzzware, I have followed the solution suggested by @vasilakisfil, and have also manually added the component to my app/components folder slightly editing the original code.

updateTemplate() {
		this.set('subLayout', null);
		scheduleOnce('afterRender', this, function() {
			try {
				let layout = null;
				if (this.get('dynamic'))
					layout = Ember.HTMLBars.compile(this.get('parsedMarkdownUnsafe'), false);
				else
					layout = Ember.HTMLBars.compile(htmlSafe(this.get('parsedMarkdownUnsafe')), false);
				this.set('subLayout', layout);
			}
			catch(error) {}
		});
	},

... or at least I believe I have edited it... I may have rolled it back to the original one somehow... but maybe this can guide you in the right direction. Keep in mind to add app.import('vendor/ember/ember-template-compiler.js'); to ember-cli.js too, though.

danieledraganti avatar May 10 '18 16:05 danieledraganti

@danidr Thanks for the reply, but I haven't understood your point. I'm trying to get Ember.HTMLBars.compile to work in production for the dynamic feature of this component with Ember 3.1.

There must be another step after app.import to use Ember.HTMLBars.compile as you do.

The source is here https://github.com/emberjs/ember.js/blob/87f7ee8a8e76c1809ad32b59eb62fc5cd35daa58/packages/ember-template-compiler/lib/system/compile.js and it specifically says "This is not present in production builds." but how do we import/include it anyway? My knowledge of JS module systems is very poor.

buzzware avatar May 11 '18 01:05 buzzware

I don’t understand why it wasn’t working before, but its working now. Weirdly, it started working when I added @glimmer/compiler as a dependency (not devDependency) in packages.json. But then I removed it, and rebuilt, and even did “rm -rf node_modules && rm-rf dist/* && npm install” and it still works. So, the only required addition is app.import('vendor/ember/ember-template-compiler.js'); to ember-cli-build.js

buzzware avatar May 11 '18 02:05 buzzware

@danidr I'm now having an issue with the markdown rendering working when the first route is loaded, but when I navigate and then hit the back button, the md-text component doesn't rerender. The model is a POJO, not Ember.Object. {{model.title}} updates fine, but {{md-text text=model.content html=true dynamic=true}} doesn't.

Would your updateTemplate code fix this? Can you paste the whole component?

I wonder if its something to do with the convoluted way dynamic rendering is happening here eg. md-text.hbs : {{#if dynamic}} {{md-dummy layout=precompiledTemplate}} {{else}} {{parsedMarkdown}} {{/if}}

buzzware avatar May 11 '18 03:05 buzzware

@buzzware Well, I have rewritten the component, but I honestly can't remember WHERE I edited it exactly... I'll just post the whole code for you here below. Sorry for spamming, but all this code is in a private repository, therefore I can't link to it directly. components/md-text.js

import Ember from 'ember';
import Component from '@ember/component';
import { computed, observer } from '@ember/object';
import { getOwner } from '@ember/application';
import { htmlSafe } from '@ember/string';
import { scheduleOnce } from '@ember/runloop';
import Remarkable from 'npm:remarkable';

export default Component.extend({
	tagName: '',

	text: '',
	breaks: true,
	typographer: true,
	linkify: true,
	linkTarget: '',
	html: false,
	extensions: true,
	dynamic: true,

	didInsertElement() {
		scheduleOnce('afterRender', this, 'updateTemplate');
	},

	highlightJsExcluded: computed(function () {
		let config;
		if (getOwner) {
			config = getOwner(this).resolveRegistration('config:environment');
		} else {
			let registry = this.container.registry || this.container._registry;
			config = registry.resolve('config:environment');
		}
		let remarkableConfig = config.remarkable || {};
		return remarkableConfig.excludeHighlightJs || false;
	}),

	highlight: computed('highlightJsExcluded', function() {

		let highlightJsExcluded = this.get('highlightJsExcluded');
		return (str, lang) => {
			if (!highlightJsExcluded) {
				if (lang === 'text' || lang === 'no-highlight') {
					return '';
				}

				if (lang && hljs.getLanguage(lang)) {
					try {
						return hljs.highlight(lang, str).value;
					} catch (err) {}
				}

				try {
					return hljs.highlightAuto(str).value;
				} catch (err) {}
			}

			return '';
		};
	}),

	parsedMarkdownUnsafe: computed('text', 'html', 'typographer', 'linkify', 'linkTarget', function () {
		var md = new Remarkable({
			breaks: this.get('breaks'),
			typographer: this.get('typographer'),
			linkify: this.get('linkify'),
			linkTarget: this.get('linkTarget'),
			html: this.get('html'),
			highlight: this.get('highlight')
		});

		if (this.get('extensions')) {
			md.core.ruler.enable([
				'abbr'
			]);
			md.block.ruler.enable([
				'footnote',
				'deflist'
			]);
			md.inline.ruler.enable([
				'footnote_inline',
				'ins',
				'mark',
				'sub',
				'sup'
			]);
		}
		md.core.ruler.disable([ 'smartquotes' ]);

		let plugins = this.get('plugins');
		if (plugins) {
			plugins.forEach((plugin) => md.use(plugin));
		}

		return md.render(this.get('text'));
	}),

	updateTemplate() {
		this.set('subLayout', null);
		scheduleOnce('afterRender', this, function() {
			try {
				let layout = null;
				if (this.get('dynamic'))
					layout = Ember.HTMLBars.compile(this.get('parsedMarkdownUnsafe'), false);
				else
					layout = Ember.HTMLBars.compile(htmlSafe(this.get('parsedMarkdownUnsafe')), false);
				this.set('subLayout', layout);
			}
			catch(error) {}
		});
	},

	observerSource: observer('text', function() { this.updateTemplate(); }),

}).reopenClass({
	positionalParams: ['text']
});

components/md-text-renderer.js

import Component from '@ember/component';

export default Component.extend({
	tagName: ''
});

templates/components/md-text.js

{{#if subLayout}}
	{{md-text-renderer layout=subLayout}}
{{/if}}

NOTES:

  • I only use dynamic text, therefore I haven't tested this component with dynamic text disabled.
  • Usage is slightly different; it's enough to say {{md-text string}} instead of {{md-text text=string}}

Let me know if it helps somehow.

danieledraganti avatar May 14 '18 09:05 danieledraganti

Big thanks @danidr ! Thats working. This dynamic rendering is very cool. I'm using it with https://github.com/buzzware/broccoli-static-site-json#remove-showdown to achieve something a bit like https://www.gatsbyjs.org ie dynamically loaded markdown with ember components

buzzware avatar May 29 '18 08:05 buzzware

@buzzware Glad to hear it worked! I'll have a look at your code.

danieledraganti avatar May 30 '18 13:05 danieledraganti