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

Addon that refreshes xterm upon webfont load #1368

Closed
wants to merge 2 commits into from

Conversation

vincentwoo
Copy link
Contributor

@vincentwoo vincentwoo commented Apr 4, 2018

Addresses #1164

I'm new to TypeScript, so I'm not sure if I've done everything the right way. I've opted to monkeypatch _setup, because we need to get into the creation flow as soon as possible (and also because only _setup references what the default font options are). It's possible to do something like require a manual call to loadWebfonts but I've opted for a more seamless approach.

The addon also doesn't add any more configuration - it assumes that any font families passed in will be webfonts. If they aren't, there may be a momentary flicker but all should continue to work.

const regular = new FontFaceObserver(originalFont).load();
const bold = new FontFaceObserver(originalFont, { weight: 'bold' }).load();

regular.constructor.all([regular, bold]).then(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this the same as Promise.all?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but without relying on importing a specific Promise library.

package.json Outdated
@@ -88,5 +88,7 @@
"webpack": "gulp webpack",
"watch": "gulp watch"
},
"dependencies": {}
"dependencies": {
"fontfaceobserver": "*"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the approach taken with zmodem here; leave it up to the consumer to include the dependency (we should add a README to the addon dir to call that out though).

zmodem = (typeof window === 'object') ? (<any>window).ZModem : {Browser: null}; // Nullify browser for tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doable. what should behavior be if you try to run the addon and the dependency is not present?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess console.warn and open normally?

(<any>terminalConstructor.prototype)._setup = function (): void {
const originalFont = this.options.fontFamily;
if (loadedFonts[originalFont]) return oldSetup.call(this);
delete this.options.fontFamily;
Copy link
Member

@Tyriar Tyriar Apr 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A more explicit loadWebfonts.load(fontFamily: string) would be preferable imo and align better with how the other addons work.

Also the font is only ever used after open is called. So what if this function was shaped more like this, rather than monkeypatching?

loadAndOpen = function (fontFamily: string, element: HTMLElement): void {
  Promise.all(...).then(() => {
    this.setOption('fontFamily', fontFamily);
    this.open(element)
  });
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One rationale for doing it on _setup is that you may create a term, write to it, and then later render it. If we know you're going to need a webfont, we can get to it before open is actually called and avoid the resize flash.

If that's not as valuable to you as having a less magical thing, I can go ahead and change the surface.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we're going to call the endpoint "load and open" we might as well just delay opening the terminal until fonts come in to avoid the reflash as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we're going to call the endpoint "load and open" we might as well just delay opening the terminal until fonts come in to avoid the reflash as well.

That's what my proposal does, it doesn't touch the DOM until the font load promises are finished?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm down. Hang tight.

@Tyriar Tyriar added this to the 3.4.0 milestone Apr 4, 2018
@vincentwoo
Copy link
Contributor Author

vincentwoo commented Apr 7, 2018

Okay, I've updated the PR. Two things:

  1. I've made the surface loadWebfontAndOpen = function (element: HTMLElement), opting not to pass the font as a separate option to the addon. I think it's a bit dangerous for users to potentially specify font in two places.

  2. I want to push for a better package story than "require the user add dependencies to the global window object". Can we add a dependency to just the addon somehow? I want a user's build system to simply import the addon and have the right thing happen. Usability of addons go down if you require the user to manually pollute the global object just to use them. Complicating this, FontFaceObserver is not fully ES6 yet and does require a require to work.

@vincentwoo
Copy link
Contributor Author

@Tyriar get a chance to see this?

@Tyriar
Copy link
Member

Tyriar commented Apr 11, 2018

I want to push for a better package story than "require the user add dependencies to the global window object". Can we add a dependency to just the addon somehow? I want a user's build system to simply import the addon and have the right thing happen. Usability of addons go down if you require the user to manually pollute the global object just to use them. Complicating this, FontFaceObserver is not fully ES6 yet and does require a require to work.

I don't want consumers who don't need zmodem or fontfaceobserver to need to download them when installing the package and also to remove them manually when they don't need them.

How about you pass it into the function then? That seems much better than relying on a global:

loadWebfontAndOpen = function (element: HTMLElement, ffo: FontFaceObserver)
webfont.loadWebfontAndOpen(element, require('fontfaceobserver'));

@vincentwoo
Copy link
Contributor Author

vincentwoo commented Apr 11, 2018 via email

@Tyriar
Copy link
Member

Tyriar commented Apr 11, 2018

That's the hope eventually (I just commented about this #1128 (comment)), in which can it could be moved to a regular dependency.

@vincentwoo
Copy link
Contributor Author

vincentwoo commented Apr 11, 2018 via email

@Tyriar
Copy link
Member

Tyriar commented Apr 11, 2018

Discoverability is then the main problem with third party addons at the moment as we don't really have a good story for that. It's up to you whether you want to do that or merge it in. Eventually this would be best to live as a third party addon not maintained by the team though.

@mofux
Copy link
Contributor

mofux commented Apr 11, 2018

Couldn't we simply add a section to our README that lists 3rd Party Addons, similar to the Real-world uses?

@Tyriar
Copy link
Member

Tyriar commented Apr 12, 2018

@mofux we could, I don't think it's a long term solution though. The readme is very long already.

@vincentwoo
Copy link
Contributor Author

I've split out this PR as its own package: https://www.npmjs.com/package/xterm-webfont. I'll leave it up to you on whether to link to it somewhere or not. I think this is a good middle ground and long-term place to be wrt addons.

@Tyriar Tyriar closed this Apr 16, 2018
@Tyriar
Copy link
Member

Tyriar commented Apr 16, 2018

#1390

@Tyriar Tyriar removed this from the 3.4.0 milestone May 17, 2018
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

Successfully merging this pull request may close these issues.

3 participants