Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic text not working on ember-cli 2.8 #25

Open
milindalvares opened this issue Sep 26, 2016 · 11 comments
Open

Dynamic text not working on ember-cli 2.8 #25

milindalvares opened this issue Sep 26, 2016 · 11 comments

Comments

@milindalvares
Copy link
Contributor

{{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.

@maciek134
Copy link
Contributor

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.

@danieledraganti
Copy link

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.

@vasilakisfil
Copy link

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

@buzzware
Copy link

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.

@danieledraganti
Copy link

@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.

@buzzware
Copy link

@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
Copy link

buzzware commented May 11, 2018

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
Copy link

buzzware commented May 11, 2018

@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}}

@danieledraganti
Copy link

danieledraganti commented May 14, 2018

@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.

@buzzware
Copy link

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

@danieledraganti
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants