Angular Marked and Inappbrowser opening all links in the system browser

China☆狼群 提交于 2019-12-24 17:06:12

问题


I am working on an Ionic app where users can post markdown content. In order to make this work, I am using the angular-marked library. In the app, I want all markdown links to be opened in the OS's default browser so I have done two things.

  1. I have written an angular directive that forces links to open in the OS' browser using the ngCordova wrapper for cordova-plugin-inappbrowser.

  2. I have set angular-marked's configuration to render all links using this directive.

The problem is that the links do not open in the system browser. They open in the current WebView. It might be that my directive is just bad or maybe directives aren't even the right thing to use in this case.

What am I doing wring in my code? How can I fix my issue to open links in the system browser?

My Directive.

  .directive('fab-extLink', ['$cordovaInAppBrowser', function($cordovaInAppBrowser){

            return {
                restrict: 'A',
                link: function(scope, elem, attrs) {
                    elem.bind('click', function(e) {
                        // Stop the link from opening.
                        e.preventDefault();

                        // Open the link with the operating system browser.
                        $cordovaInAppBrowser.open(attrs.href, '_system');
                    });
                }
            };
    }])

My Config

.config( [
      '$compileProvider',
      'markedProvider',
      function( $compileProvider, markedProvider)
      {
        $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);

        // When markdown is rendered use the external link directive.
        markedProvider.setRenderer({
          link: function(href, title, text) {
            return '<a fab-extLink href="' + href + '"' + (title ? ' title="' + title + '"' : '') + '>' + text + '</a>';
          }
        });
      }
    ])

回答1:


There are two problems with your code

1. the name of an angular directive should be in camelCase, it will be converted to kebab-case in HTML. This is very easy to fix, just change

 .directive('fab-extLink', ['$cordovaInAppBrowser', function($cordovaInAppBrowser){

to

 .directive('fabExtlink', ['$cordovaInAppBrowser', function($cordovaInAppBrowser){

2. in your case, there is <a fab-extlink> in your HTML, but angular doesn't $compile (instantiate) it.

This is a difficult one (if you don't want to monkey-patch angular-marked).

angular-marked uses element.html(marked(text, scope.opts || null)); to set the inner HTML of the element, it skips angular's compiling process, so directives aren't initialized..

One workaround is to use a global function (not elegant I know):

Define it in app.run:

.run(function ($cordovaInAppBrowser) {
  window.openInSystemBrowser=function(link){
     $cordovaInAppBrowser.open(link, '_system');
  };

and config angular-marked to use onclick, so that it works independent of angular.

markedProvider.setRenderer({
        link: function (href, title, text) {
          return '<a onclick="openInSystemBrowser(\'' + href + '\')"' + (title ? ' title="' + title + '"' : '') + '>' + text + '</a>';
        }
      });

The other way I can think of is to fork and patch angular-marked.


The monkey-patch solution:

  1. Open angular-marked.js
  2. replace

    element.html(marked(text, scope.opts || null));
    

    with

    element.replaceWith($compile(marked(text, scope.opts || null))(scope));
    

update2

I checked the repo, the newest version of angular-marked (v1.2) supports an attribute called compile, to do exactly that.

e.g.

<marked compile="true">
          # Markdown [Google](http://www.google.com)
          *It works!*
</marked>

So, in conclusion..


TLDR version

1. change

 .directive('fab-extLink', ...

to

 .directive('fabExtlink', ...

2. add attribute compile='true' to <marked> directive




回答2:


If you are looking for a easy way to open links in native browsers on mobile devices with marked can you just try setting this in your angular .config:

markedProvider.setRenderer({
  link: function(href, title, text) {
    return "<a href='" + href + "'" + (title ? " title='" + title + "'" : '') + " onclick='window.open("+href+", '_system')'" + " target='_system'>" + text + "</a>";
  }
});

And then you would need to bind an onDeviceReady function somewhere like this:

document.addEventListener('deviceready', onDeviceReady, false);

function onDeviceReady() {
  window.open = cordova.InAppBrowser.open;
}


来源:https://stackoverflow.com/questions/36948337/angular-marked-and-inappbrowser-opening-all-links-in-the-system-browser

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!