Load a graph from a generated url

2019-08-04 00:03发布

问题:

I want to build an online html/css/javascript playground. When the code draws a graph, I want to be able to generate a url, with which users could load this graph in a browser.

At the moment, in the playground, I have a button that links to the function generateUrl:

$scope.generateUrl = function () {
    urls.create({
        // allCode is a string like "<html><body><canvas ...>...</canvas><script>...</script></html>"
        content: $scope.allCode
    }).success(function (url) {
        alert(url._id)
    });
};

Then, I want to load with the id of a url like localhost:3000/urls/58a56d0962bd39979d142e27 in a browser:

app.config(['$stateProvider', function ($stateProvider) {
    $stateProvider
        .state('urls', {
            url: '/urls/{id}',
            template: "{{url.content}}",
            controller: 'UrlCtrl',
            resolve: {
                url: ['$stateParams', 'urls', function ($stateParams, urls) {
                    return urls.get($stateParams.id);
                }]
            }
        })

However, the above code just shows the string rather than the graph:

Additionally, it is embedded in <ui-view></ui-view> of my global index.ejs. The behaviour is expected, but it is not what I want users to see when they load www.mysite.com/urls/58a56d0962bd39979d142e27.

Does anyone know how to set up loading a graph from a generated url?

回答1:

I believe that you need to use Angular's Strict Contextual Escaping service, more known as $sce.

Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain contexts to result in a value that is marked as safe to use for that context. One example of such a context is binding arbitrary html controlled by the user via ng-bind-html. We refer to these contexts as privileged or SCE contexts.

So, you can either use the ngBindHtml directive, instead of plain interpolation.

<div ng-bind-html="url.content"></div>

Or, you could also inject $sce on your url resolve function and call trustAsHtml method:

resolve: {
    url: ['$sce', '$stateParams', 'urls', function ($sce, $stateParams, urls) {
        return $sce.trustAsHtml(urls.get($stateParams.id));
    }]
}

I'm not sure what's gonna happen if your HTML code contains the html and body tags. Maybe you'll need to remove those.