Подтвердить что ты не робот

Markdown с директивами AngularJS

Я пытаюсь сделать директиву для HTML, используя AngularJS, чтобы я мог отображать Markdown в браузере. Я хочу иметь тег <markdown> с атрибутом src, который будет загружать указанный файл и отображать его правильно.

Я частично реализовал это следующим образом:

function Main($scope) {
    $scope.theContent = '#asgakfgajgfas\n##akfaljfqpo\ndhvkajvlbndvm';
};

angular.module('myApp', [])
    .directive("markdown", function ($compile) {
    return {
        restrict: 'E',
        require: 'model',
        scope: {
            value: "=model"
        },
        template: '<div ng-bind-html-unsafe="value | markdown"></div>'
    };
}).filter('markdown', function () {
    var converter = new Showdown.converter();
    return function (value) {
        return converter.makeHtml(value || '');
    };
});

И соответствующий HTML -

<div ng-controller="Main">
    <markdown model="theContent"></markdown>
</div>

Вот ссылка jsFiddle (на примере Джона Линквиста) для вышеуказанного кода. Это не работает с атрибутом src, однако он может загрузить текстовую строку разметки, указанную в модели.

Не могли бы вы рассказать мне, как я могу изменить этот код, чтобы загрузить файл, указанный в теге src. Я думал об использовании $http, предоставленного AngularJS, но не смог заставить себя использовать его внутри определения директивы.

То, что я хотел бы достичь, - <markdown src="a/b/c.md" />

4b9b3361

Ответ 1

Наконец-то я придумал решение.

// Render markdown in the HTML page
app.directive("markdown", function ($compile, $http) {
    var converter = new Showdown.converter();
    return {
        restrict: 'E',
        replace: true,
        link: function (scope, element, attrs) {
            if ("src" in attrs) {
                $http.get(attrs.src).then(function(data) {
                    element.html(converter.makeHtml(data.data));
                });
            } else {
                element.html(converter.makeHtml(element.text()));
            }
        }
    };
});

Я определяю пользовательскую функцию link, которая либо берет содержимое тегов <markdown>, либо корректно отображает их, либо получает содержимое файла, указанное в атрибуте src, и делает это.

Ответ 2

Другая альтернатива, основанная на ответе выше. Этот использует angular eval, watch и sanitize, что означает, что он полезен для живого редактирования, дезинфицирует html, который необходим, поскольку markdown оставляет встроенный html, такой как тег script как есть, и использует angular для доступа к данным.

Использование

Контроллер:

 $scope.data = {markdown:"#H1"} 

Вид:

<div markdown="data.markdown">
</div>

<textarea ng-model="data.markdown"></textarea>

Код:

angular.module('markdown',['ngSanitize']).directive('markdown', function ($sanitize) {
    var converter = new Showdown.converter();
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            function renderMarkdown() {
                var htmlText = converter.makeHtml(scope.$eval(attrs.markdown)  || '');
                element.html($sanitize(htmlText));
            }
            scope.$watch(attrs.markdown, function(){
                renderMarkdown();
            });
            renderMarkdown();
        }
    }
});

Ответ 3

Вот простейшее общее решение, которое я мог бы использовать, используя $sanatize или $sce не:

http://plnkr.co/edit/6OK0RcMChmD1S3JtfItp?p=preview

  <body ng-app="myApp">

    <textarea ng-model="test"></textarea>
    <div markdown="test"></div>

    <script src="//code.angularjs.org/1.3.0/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/showdown/0.3.1/showdown.min.js"></script>

    <script>
      angular.module('myApp', [])
        .run(function($rootScope) {
          $rootScope.test = '#foo\r- bar\r- baz'
        })
        .directive('markdown', function () {
              var converter = new Showdown.converter();
              return {
                  restrict: 'A',
                  link: function (scope, element, attrs) {
                      function renderMarkdown() {
                          var htmlText = converter.makeHtml(scope.$eval(attrs.markdown)  || '');
                          element.html(htmlText);
                      }
                      scope.$watch(attrs.markdown, renderMarkdown);
                      renderMarkdown();
                  }
              };
          });
    </script>
  </body>

РЕЗУЛЬТАТ:

Foo

  • бар
  • Баз