最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Ace text editor - "require" fails if the source is minified - Stack Overflow

programmeradmin2浏览0评论

I am attempting to use the ace text editor with angular, and one of the needed behaviors requires a call to ace.require.

I've included the appropriate files, but I am seeing that if I minify my javascript source, that doesn't work anymore. This is clearly because the path bees invalid, but I'm not sure how to handle the situation except to manually load the mentioned files outside of my optimized bundles. I am using ASP.NET MVC Web Optimization Framework to load my javascripts as "bundles" that are pact and minified.

I am using ui-ace directive to load it, but I have tested without any directive and the behavior is the same whether or not I am going through angular.

Has anyone else discovered a workaround to this?

It's pretty simple code ...

Bundle

bundles.Add( new ScriptBundle( "~/bundles/js/ace" )
    // include the ace text editor
    .Include( "~/application/assets/scripts/ace/ace.js" )
    .Include( "~/application/assets/scripts/ace/ext-language_tools.js" )));

Javascript

    if (angular.isDefined(opts.require)) {
        opts.require.forEach(function (n) {
            window.ace.require(n);
        });
    }

This can also just be typed explicitly as ...

ace.require('ace/ext/language_tools');

HTML

<div ng-model="Model.Scripting"
     ui-ace="{
        useWrapMode: true,
        showGutter: true,
        theme: 'chrome',
        mode: 'javascript',
        require: ['ace/ext/language_tools'],
        advanced: {
            enableSnippets: true,
            enableBasicAutopletion: true,
            enableLiveAutopletion: true
        }
    }">
</div>

HOW TO REPRODUCE

Since I cannot figure out a way to get the whole thing to you exactly as it needs to be, I've recreated the behavior using nodejs, bower, and gulp.

NODE JS/BOWER

Start by running these mands in nodejs, in a new folder.

npm install bower npm install gulp npm install gulp-concat npm install gulp-rename npm install gulp-uglify npm install run-sequence

bower install angular bower install ace-builds bower install angular-ui-ace

GULP

You can use this gulpfile.js to build the script file.

var
  gulp = require('gulp'),
  concat = require('gulp-concat'),
  rename = require('gulp-rename'),
  uglify = require('gulp-uglify'),
  sequence = require('run-sequence');

gulp.task('default', function() {
  return sequence([
    "ace"
  ]);
});

gulp.task('ace', function() {
  return gulp.src([
    'bower_ponents/angular/angular.js',
    'bower_ponents/angular-ui-ace/ui-ace.js',

    'bower_ponents/ace-builds/src-noconflict/ace.js',
    'bower_ponents/ace-builds/src-noconflict/mode-javascript.js',
    'bower_ponents/ace-builds/src-noconflict/worker-javascript.js',
    'bower_ponents/ace-builds/src-noconflict/theme-chrome.js',
    'bower_ponents/ace-builds/src-noconflict/snippets/text.js',
    'bower_ponents/ace-builds/src-noconflict/snippets/javascript.js'])
    .pipe(concat('scripts.js'))
    .pipe(uglify())
    .pipe(gulp.dest('js'));
});

INDEX.HTML

This is an HTML file that can reproduce the problem.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="js/scripts.js"></script>
    <script type="text/javascript">
        (function () {
            var ace = window.ace = window.ace || { };
            ace.initialize = function(editor) {
                ace.require("ace/ext/language_tools");

                editor.setTheme("ace/theme/chrome");
                editor.getSession().setMode("ace/mode/javascript");

                // options
                editor.setOptions({
                    showGutter: true,
                    showPrintMargin: false,
                    enableBasicAutopletion: true,
                    enableSnippets: true,
                    enableLiveAutopletion: true,
                    fontSize: '14px',
                    fontFamily: 'Consolas'
                });
            };
        })();
    </script>
    <script type="text/javascript">
        angular.module('app', ['ui.ace'])
                .controller('HomeController',['$scope', function($scope){
                    $scope.aceLoaded = function(_editor){
                        ace.initialize(_editor);
                    };

                    $scope.Model = {
                        Scripting: ""
                    }
                }]);
    </script>
</head>
<body ng-app="app" ng-controller="HomeController">
    <div ui-ace="{ onLoad: aceLoaded }"></div>
</body>
</html>

I am attempting to use the ace text editor with angular, and one of the needed behaviors requires a call to ace.require.

I've included the appropriate files, but I am seeing that if I minify my javascript source, that doesn't work anymore. This is clearly because the path bees invalid, but I'm not sure how to handle the situation except to manually load the mentioned files outside of my optimized bundles. I am using ASP.NET MVC Web Optimization Framework to load my javascripts as "bundles" that are pact and minified.

I am using ui-ace directive to load it, but I have tested without any directive and the behavior is the same whether or not I am going through angular.

Has anyone else discovered a workaround to this?

It's pretty simple code ...

Bundle

bundles.Add( new ScriptBundle( "~/bundles/js/ace" )
    // include the ace text editor
    .Include( "~/application/assets/scripts/ace/ace.js" )
    .Include( "~/application/assets/scripts/ace/ext-language_tools.js" )));

Javascript

    if (angular.isDefined(opts.require)) {
        opts.require.forEach(function (n) {
            window.ace.require(n);
        });
    }

This can also just be typed explicitly as ...

ace.require('ace/ext/language_tools');

HTML

<div ng-model="Model.Scripting"
     ui-ace="{
        useWrapMode: true,
        showGutter: true,
        theme: 'chrome',
        mode: 'javascript',
        require: ['ace/ext/language_tools'],
        advanced: {
            enableSnippets: true,
            enableBasicAutopletion: true,
            enableLiveAutopletion: true
        }
    }">
</div>

HOW TO REPRODUCE

Since I cannot figure out a way to get the whole thing to you exactly as it needs to be, I've recreated the behavior using nodejs, bower, and gulp.

NODE JS/BOWER

Start by running these mands in nodejs, in a new folder.

npm install bower npm install gulp npm install gulp-concat npm install gulp-rename npm install gulp-uglify npm install run-sequence

bower install angular bower install ace-builds bower install angular-ui-ace

GULP

You can use this gulpfile.js to build the script file.

var
  gulp = require('gulp'),
  concat = require('gulp-concat'),
  rename = require('gulp-rename'),
  uglify = require('gulp-uglify'),
  sequence = require('run-sequence');

gulp.task('default', function() {
  return sequence([
    "ace"
  ]);
});

gulp.task('ace', function() {
  return gulp.src([
    'bower_ponents/angular/angular.js',
    'bower_ponents/angular-ui-ace/ui-ace.js',

    'bower_ponents/ace-builds/src-noconflict/ace.js',
    'bower_ponents/ace-builds/src-noconflict/mode-javascript.js',
    'bower_ponents/ace-builds/src-noconflict/worker-javascript.js',
    'bower_ponents/ace-builds/src-noconflict/theme-chrome.js',
    'bower_ponents/ace-builds/src-noconflict/snippets/text.js',
    'bower_ponents/ace-builds/src-noconflict/snippets/javascript.js'])
    .pipe(concat('scripts.js'))
    .pipe(uglify())
    .pipe(gulp.dest('js'));
});

INDEX.HTML

This is an HTML file that can reproduce the problem.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script type="text/javascript" src="js/scripts.js"></script>
    <script type="text/javascript">
        (function () {
            var ace = window.ace = window.ace || { };
            ace.initialize = function(editor) {
                ace.require("ace/ext/language_tools");

                editor.setTheme("ace/theme/chrome");
                editor.getSession().setMode("ace/mode/javascript");

                // options
                editor.setOptions({
                    showGutter: true,
                    showPrintMargin: false,
                    enableBasicAutopletion: true,
                    enableSnippets: true,
                    enableLiveAutopletion: true,
                    fontSize: '14px',
                    fontFamily: 'Consolas'
                });
            };
        })();
    </script>
    <script type="text/javascript">
        angular.module('app', ['ui.ace'])
                .controller('HomeController',['$scope', function($scope){
                    $scope.aceLoaded = function(_editor){
                        ace.initialize(_editor);
                    };

                    $scope.Model = {
                        Scripting: ""
                    }
                }]);
    </script>
</head>
<body ng-app="app" ng-controller="HomeController">
    <div ui-ace="{ onLoad: aceLoaded }"></div>
</body>
</html>
Share Improve this question edited Sep 13, 2014 at 23:08 Ciel asked Sep 13, 2014 at 21:53 CielCiel 4,4408 gold badges55 silver badges112 bronze badges 3
  • can you setup a fiddle? – Matt Way Commented Sep 13, 2014 at 22:17
  • I will try to get you something here momentarily. I think I figured out a way to get you a sample. – Ciel Commented Sep 13, 2014 at 22:54
  • Alright. I've provided the instructions for easily re-creating the entire thing. Is that useful at all? – Ciel Commented Sep 13, 2014 at 23:08
Add a ment  | 

2 Answers 2

Reset to default 6

For ace.require to work you need to add ext-language_tools to your gulp.task("ace")

'bower_ponents/ace-builds/src-noconflict/ace.js',
'bower_ponents/ace-builds/src-noconflict/ext-language_tools.js',
'bower_ponents/ace-builds/src-noconflict/mode-javascript.js',

bower_ponents/ace-builds/src-noconflict/worker-javascript.js isn't needed in the bundle since it needs to be loaded in the webworker. For that to work you need to configure workerPath to point to the right folder

ace.initialize = function(editor) {
    ace.require("ace/config").set("workerPath",
        "bower_ponents/ace-builds/src-min-noconflict");
    ace.require("ace/ext/language_tools");

and for ace not being visible initially because of it's height being set to 0 see this question: Ace editor doesn't work with bootstrap

also note that fontFamily: 'Consolas' might cause problems on systems where that font is missing, so it's better to add a fallback to monospace like fontFamily: 'Consolas', monospace

Please refer to my answer on github (lahdo) if above solution is not working for you (workers are still not loaded properly):

https://github./angular-ui/ui-ace/issues/106

发布评论

评论列表(0)

  1. 暂无评论