Skip to content

Commit

Permalink
Merge pull request #4558 from ajaxorg/csp-3
Browse files Browse the repository at this point in the history
generate css files in build to use with csp
  • Loading branch information
nightwing authored Sep 30, 2021
2 parents 8364cd4 + 910c09a commit d957259
Show file tree
Hide file tree
Showing 58 changed files with 291 additions and 72 deletions.
116 changes: 111 additions & 5 deletions Makefile.dryice.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
*
* ***** END LICENSE BLOCK ***** */

/*global Buffer*/

var fs = require("fs");
var path = require("path");
var copy = require('architect-build/copy');
Expand Down Expand Up @@ -447,10 +449,113 @@ function buildAce(options, callback) {
sanityCheck(options, callback);
if (options.noconflict && !options.compress)
buildTypes();

extractCss(options, function() {
if (callback)
return callback();
console.log("Finished building " + getTargetDir(options));

});
}
}

function extractCss(options, callback) {
var dir = BUILD_DIR + "/src" + (options.noconflict ? "-noconflict" : "");
var filenames = fs.readdirSync(dir);
var css = "";
var images = {};
var usedCss = {};
filenames.forEach(function(filename) {
var stat = fs.statSync(dir + "/" + filename);
if (stat.isDirectory()) return;
var value = fs.readFileSync(dir + "/" + filename, "utf8");

if (callback)
return callback();
console.log("Finished building " + getTargetDir(options));
var cssImports = detectCssImports(value);

if (/theme-/.test(filename)) {
var name = filename.replace(/^theme-|\.js$/g, "");
var themeCss = "";
for (var i in cssImports) {
themeCss += cssImports[i];
}
themeCss = extractImages(themeCss, name, "..");
build.writeToFile({code: themeCss}, {
outputFolder: BUILD_DIR + "/css/theme",
outputFile: name + ".css"
}, function() {});
} else if (cssImports) {
css += "\n/*" + filename + "*/";
for (var i in cssImports) {
if (usedCss[cssImports[i]]) continue;
usedCss[cssImports[i]] = true;
css += "\n" + cssImports[i];
}
}
});

css = extractImages(css, "main", ".").replace(/^\s*/gm, "");
build.writeToFile({code: css}, {
outputFolder: BUILD_DIR + "/css",
outputFile: "ace.css"
}, function() {
saveImages();
callback();
});

function detectCssImports(code) {
code = code.replace(/^\s*\/\/.+|^\s*\/\*[\s\S]*?\*\//gm, "");

var stringRegex = /^("(?:[^"\\]|\\[\d\D])*"|'(?:[^'\\]|\\[\d\D])*'|)/;
var importCssRegex = /\.importCssString\(\s*(?:([^,)"']+)|["'])/g;

var match;
var cssImports;
while (match = importCssRegex.exec(code)) {
if (match[1]) {
var locationRegex = new RegExp("[^.]" + match[1] + /\s*=\s*['"]/.source);
match = locationRegex.exec(code);
if (!match) continue;
}
var index = match.index + match[0].length - 1;
if (cssImports && cssImports[index]) continue;
var cssString = stringRegex.exec(code.slice(index))[0];
if (!cssString) continue;
if (!cssImports) cssImports = {};
cssImports[index] = cssString.slice(1, -1).replace(/\\(.|\n)/g, function(_, ch) {
if (ch == "n") return "";
return ch;
});
}
return cssImports;
}

function extractImages(css, name, directory) {
var imageCounter = 0;
return css.replace(
/url\(\s*"data:([^"\\]|\\.)+"\s*\)|url\(\s*'data:([^'\\]|\\.)+'\s*\)|url\(data:[^)]+\)/g,
function(url) {
var data = url.slice(4, -1).trim();
if (/["']/.test(data[0])) {
data = data.slice(1, -1).replace(/\\(.)/g, "$1");
}
data = data.slice(5);
var i = data.indexOf(",");
if (i == -1) {
console.error(url);
return url;
}
var buffer = Buffer.from(data.slice(i + 1), "base64");
imageCounter++;
var imageName = name + "-" + imageCounter + ".png";
images[imageName] = buffer;
return "url(\"" + directory + "/" + imageName + "\")";
}
);
}
function saveImages() {
for (var imageName in images) {
fs.writeFileSync(BUILD_DIR + "/css/" + imageName, images[imageName]);
}
}
}

Expand All @@ -466,7 +571,8 @@ function getLoadedFileList(options, callback, result) {
if (!deps[p]) deps[p] = 1;
});
});
delete deps["ace/theme/textmate"];
if (options.projectType == "theme")
delete deps["ace/theme/textmate"];
deps["ace/ace"] = 1;
callback(Object.keys(deps));
}
Expand Down Expand Up @@ -549,7 +655,7 @@ function namespace(ns) {
function exportAce(ns, modules, requireBase, extModules) {
requireBase = requireBase || "window";
return function(text) {
/*globals REQUIRE_NS, MODULES, NS*/
/*globals REQUIRE_NS, MODULES*/
var template = function() {
(function() {
REQUIRE_NS.require(MODULES, function(a) {
Expand Down
38 changes: 38 additions & 0 deletions demo/csp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Content-Security-Policy" content="
style-src 'self' ;
img-src 'self' ;
script-src 'self' 'nonce-bootstrap-script';
worker-src 'self' blob:
">
<title>Editor</title>
</head>
<body>
<pre id="editor"></pre>

<script src="../build/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<link rel="stylesheet" href="../build/css/ace.css">
<link rel="stylesheet" href="../build/css/theme/tomorrow_night_eighties.css">

<script nonce="bootstrap-script">

ace.config.set("useStrictCSP", true);

var editor = ace.edit("editor", {
theme: "ace/theme/tomorrow_night_eighties",
mode: "ace/mode/html",
maxLines: 30,
wrap: true,
autoScrollEditorIntoView: true
});

</script>

<script src="./show_own_source.js"></script>

</body>
</html>
16 changes: 16 additions & 0 deletions lib/ace/ace_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) {
"use strict";

var dom = require("./lib/dom");
var ace = require("./ace");
var assert = require("./test/assertions");

Expand Down Expand Up @@ -116,6 +117,21 @@ module.exports = {

done();
});
},
"test: useStrictCSP": function() {
ace.config.set("useStrictCSP", undefined);
function getStyleNode() {
return document.getElementById("test.css");
}
assert.ok(!getStyleNode());
dom.importCssString("test{}", "test.css", false);
assert.ok(!getStyleNode());

ace.config.set("useStrictCSP", true);
assert.ok(!getStyleNode());

ace.config.set("useStrictCSP", false);
assert.ok(getStyleNode());
}
};

Expand Down
2 changes: 1 addition & 1 deletion lib/ace/autocomplete/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ dom.importCssString("\
line-height: 1.4;\
background: #25282c;\
color: #c1c1c1;\
}", "autocompletion.css");
}", "autocompletion.css", false);

exports.AcePopup = AcePopup;
exports.$singleLineEditor = $singleLineEditor;
Expand Down
7 changes: 5 additions & 2 deletions lib/ace/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ define(function(require, exports, module) {
var lang = require("./lib/lang");
var oop = require("./lib/oop");
var net = require("./lib/net");
var dom = require("./lib/dom");
var AppConfig = require("./lib/app_config").AppConfig;

module.exports = exports = new AppConfig();
Expand All @@ -51,13 +52,13 @@ var options = {
suffix: ".js",
$moduleUrls: {},
loadWorkerFromBlob: true,
sharedPopups: false
sharedPopups: false,
useStrictCSP: null
};

exports.get = function(key) {
if (!options.hasOwnProperty(key))
throw new Error("Unknown config key: " + key);

return options[key];
};

Expand All @@ -66,6 +67,8 @@ exports.set = function(key, value) {
options[key] = value;
else if (this.setDefaultValue("", key, value) == false)
throw new Error("Unknown config key: " + key);
if (key == "useStrictCSP")
dom.useStrictCSP(value);
};

exports.all = function() {
Expand Down
1 change: 1 addition & 0 deletions lib/ace/config_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ if (typeof process !== "undefined") {
define(function(require, exports, module) {
"use strict";

var dom = require("./config");
var config = require("./config");
var assert = require("./test/assertions");

Expand Down
2 changes: 1 addition & 1 deletion lib/ace/ext/code_lens.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,6 @@ dom.importCssString("\
.ace_dark > .ace_codeLens > a:hover {\
color: #4e94ce;\
}\
", "");
", "codelense.css", false);

});
2 changes: 1 addition & 1 deletion lib/ace/ext/error_marker.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,6 @@ dom.importCssString("\
border-left-color: transparent!important;\
top: -5px;\
}\
", "");
", "error_marker.css", false);

});
2 changes: 1 addition & 1 deletion lib/ace/ext/menu_tools/overlay_page.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ define(function(require, exports, module) {
'use strict';
var dom = require("../../lib/dom");
var cssText = require("../../requirejs/text!./settings_menu.css");
dom.importCssString(cssText);
dom.importCssString(cssText, "settings_menu.css", false);

/**
* Generates an overlay for displaying menus. The overlay is an absolutely
Expand Down
2 changes: 1 addition & 1 deletion lib/ace/ext/prompt.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ dom.importCssString(".ace_prompt_container {\
background: white;\
border-radius: 2px;\
box-shadow: 0px 2px 3px 0px #555;\
}");
}", "promtp.css", false);


exports.prompt = prompt;
Expand Down
2 changes: 1 addition & 1 deletion lib/ace/ext/searchbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var keyUtil = require("../lib/keys");

var MAX_COUNT = 999;

dom.importCssString(searchboxCss, "ace_searchbox");
dom.importCssString(searchboxCss, "ace_searchbox", false);

var SearchBox = function(editor, range, showReplaceForm) {
var div = dom.createElement("div");
Expand Down
2 changes: 0 additions & 2 deletions lib/ace/ext/textarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ var UA = require("../lib/useragent");
var net = require("../lib/net");
var ace = require("../ace");

require("../theme/textmate");

module.exports = exports = ace;

/*
Expand Down
4 changes: 2 additions & 2 deletions lib/ace/incremental_search.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ exports.IncrementalSearch = IncrementalSearch;
**/

var dom = require('./lib/dom');
dom.importCssString && dom.importCssString("\
dom.importCssString("\
.ace_marker-layer .ace_isearch-result {\
position: absolute;\
z-index: 6;\
Expand All @@ -282,7 +282,7 @@ div.ace_isearch-result {\
.ace_dark div.ace_isearch-result {\
background-color: rgb(100, 110, 160);\
box-shadow: 0 0 4px rgb(80, 90, 140);\
}", "incremental-search-highlighting");
}", "incremental-search-highlighting", false);

// support for default keyboard handler
var commands = require("./commands/command_manager");
Expand Down
2 changes: 1 addition & 1 deletion lib/ace/keyboard/vim.js
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,7 @@ dom.importCssString(".normal-mode .ace_cursor{\
width: 20em;\
color: inherit;\
font-family: monospace;\
}", "vimMode");
}", "vimMode", false);
(function() {
function dialogDiv(cm, template, bottom) {
var wrap = cm.ace.container;
Expand Down
Loading

0 comments on commit d957259

Please sign in to comment.