Skip to content

Commit 4e92663

Browse files
authored
Merge pull request #1 from compiler-explorer/audit-fix-toolchain
Audit fix toolchain
2 parents 03565ed + 5492e3c commit 4e92663

26 files changed

Lines changed: 5131 additions & 5490 deletions

.github/workflows/ci.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ ce-main ]
6+
pull_request:
7+
8+
jobs:
9+
build-and-test:
10+
runs-on: ubuntu-latest
11+
env:
12+
# Karma's ChromeHeadlessNoSandbox launcher uses this; Chrome is
13+
# preinstalled on the ubuntu-latest runner.
14+
CHROME_BIN: /usr/bin/google-chrome-stable
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- uses: actions/setup-node@v4
19+
with:
20+
node-version: '22'
21+
cache: npm
22+
23+
- name: Install grunt-cli
24+
run: npm install -g grunt-cli
25+
26+
- name: Install dependencies
27+
run: npm ci
28+
29+
- name: Test and lint
30+
run: npm test
31+
32+
- name: Build distributable
33+
run: grunt dist

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ typings
33
.idea
44
npm-debug.log
55
lib/
6+
dist/

.travis.yml

Lines changed: 0 additions & 5 deletions
This file was deleted.

CLAUDE.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## What this is
6+
7+
Compiler Explorer's fork of [Golden Layout](https://golden-layout.com/) 1.5.x — a multi-window/multi-screen JavaScript layout manager. The default branch is `ce-main`. The library is plain ES5 JavaScript (not TypeScript) and has a hard runtime dependency on **jQuery**, expected to be available as `window.$`.
8+
9+
## Commands
10+
11+
The build is driven by Grunt (needs `grunt-cli` installed globally: `npm install -g grunt-cli`).
12+
13+
- `grunt dist` — full build: regenerates the namespace + index, compiles LESS themes, and concatenates `dist/goldenlayout.js` and `dist/goldenlayout.min.js`. Run this to produce distributable output.
14+
- `grunt build` — only the codegen step (`build/task.js`): walks `src/js`, regenerates `build/ns.js` and `index.html` (from `index.hbs`).
15+
- `grunt less` — compile `src/less/*.less` themes into `src/css/*.css`.
16+
- `grunt watch` (the default task) — rebuild and re-test on changes to `src/**` / `test/**`, with livereload.
17+
- `npm test` — runs `grunt test` (Karma single-run under headless Chrome) then `npm run tslint`. Needs Chrome/Chromium on `PATH` (or `CHROME_BIN` set); the `ChromeHeadlessNoSandbox` launcher in `karma.conf.js` runs with `--no-sandbox` for CI/root.
18+
- `grunt karma:unit` — local Karma runner (Chrome, watch mode, `singleRun: false`).
19+
- `npm run tslint` — lints `**/*.ts` (primarily `index.d.ts`); config in `tslint.json`.
20+
21+
There is no single-test runner flag; narrow a Karma run by temporarily editing the `files` globs in `karma.conf.js`, or `fdescribe`/`fit` in the relevant `test/*.js` spec.
22+
23+
The dist pipeline uses native grunt plugins: `grunt-contrib-concat` (wraps the concatenated sources in the `(function($){…})(window.$)` IIFE via its banner/footer) then `grunt-contrib-uglify` for the `.min.js`. The old gulp/`grunt-gulp` pipeline (and the long-deprecated `gulpfile.js`) were removed — they pinned `gulp@3`, which is incompatible with modern Node.
24+
25+
The specs were written for Jasmine 1.x (legacy `runs`/`waits`/`waitsFor` + `spy.calls.length`/`spy.mostRecentCall`). `test/jasmine-compat.js` shims that API onto Jasmine 2+ and must load before the spec files (it's listed first in `karma.conf.js`). Jasmine randomisation is disabled (`client.jasmine.random = false`) because specs share state across `it` blocks.
26+
27+
## Build model (important)
28+
29+
The shipped file is produced by **plain concatenation, not a module bundler**. There is no `require`/`import` between source files — everything hangs off a single global `lm` namespace object.
30+
31+
- `build/ns.js` declares `var lm = {config, container, controls, errors, items, utils}` and is the **first** file concatenated. It is generated from the `src/js` directory tree by `grunt build`, so adding a new subdirectory under `src/js` requires regenerating it.
32+
- Concatenation order (from `Gruntfile.js` / `karma.conf.js`): `build/ns.js`, then `utils/utils.js`, `utils/EventEmitter.js`, `utils/DragListener.js`, then the rest of `src/js/**/*.js`. These are loaded early because other files reference them at definition time. (grunt's globbing dedupes the explicitly-listed utils against the trailing glob, preserving first-occurrence order.)
33+
- The concatenated result is wrapped in `(function($){ ... })(window.$)`, which is how `$` is in scope everywhere without an explicit import.
34+
35+
Consequence: when adding a file, place classes on the correct `lm.<namespace>.<Name>` slot, and remember that anything referenced at load time (not just call time) must be concatenated earlier.
36+
37+
## Architecture
38+
39+
Everything is a mixin-based ES5 "class" using `lm.utils.copy(Proto.prototype, {...})` for methods and `lm.utils.extend` for inheritance. `lm.utils.EventEmitter.call(this)` is mixed into most constructors.
40+
41+
- **`lm.LayoutManager`** (`src/js/LayoutManager.js`) — the public entry point, exported as `GoldenLayout`. Owns the config, the root content item, popout windows, drag sources, and the component registry. `registerComponent(name, ctor)` maps a `componentName` to a constructor; `_typeToItem` maps config `type` (`row`/`column`/`stack`/`component`) to item classes. `LayoutManager.__lm = lm` exposes the private namespace.
42+
- **Content items** (`src/js/items/`) — all inherit from `AbstractContentItem`, which provides the tree (`contentItems`, `parent`, traversal, lifecycle `_$init`/`_$show`/`_$hide`/`_$destroy`) and event bubbling. Concrete types: `Root`, `RowOrColumn` (one class, `isColumn` flag), `Stack`, `Component`. `Component` wraps a user-registered constructor and instantiates an `lm.container.ItemContainer`.
43+
- **Controls** (`src/js/controls/`) — UI/interaction pieces: `Header`, `Tab`, `HeaderButton`, `Splitter`, `DragProxy`/`DragSource`, `DropTargetIndicator`, `TransitionIndicator`, `BrowserPopout` (native popup windows).
44+
- **Container** (`src/js/container/ItemContainer.js`) — the object handed to user components; bridges component state/size to the layout.
45+
- **Utils** (`src/js/utils/`) — `EventEmitter`, `EventHub` (cross-window events), `DragListener`, `ConfigMinifier` (the one-letter key compression behind `LayoutManager.minifyConfig`/`unminifyConfig`), `ReactComponentHandler` (registered automatically as the `lm-react-component`), and `utils.js` helpers.
46+
- **Config** (`src/js/config/`) — `defaultConfig.js`, `ItemDefaultConfig.js`.
47+
48+
State persistence: layouts serialize to/from a config object (`toConfig()` / construct from config), optionally minified via `ConfigMinifier`.
49+
50+
## Types and tests
51+
52+
- `index.d.ts` is the hand-maintained TypeScript declaration for the public API. Keep it in sync when changing public methods/signatures; it is what `tslint` checks.
53+
- Tests are Jasmine specs in `test/*.js`, run in a real/headless browser via Karma (they need jQuery + the concatenated source, see `karma.conf.js` file list). `test/test-tools.js` holds shared helpers. Note `test/xss_tests.js` — title/HTML sanitization is security-relevant; preserve escaping (`lm.utils.stripTags`) when touching titles/tabs.
54+
55+
## Manual dev harness
56+
57+
`index.html` (generated) + `start.js` load the built library against `?layout=responsive|tab-dropdown` query params for manual testing of standard/responsive/tab-dropdown layouts and theme switching.

Gruntfile.js

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
var gulp = require( 'gulp' );
2-
var concat = require( 'gulp-concat' );
3-
var uglify = require( 'gulp-uglify' );
4-
var insert = require( 'gulp-insert' );
5-
var watch = require( 'gulp-watch' );
6-
71
/* global require */
82
module.exports = function( grunt ) {
93
grunt.registerTask( 'build', require( './build/task' ) );
@@ -13,15 +7,9 @@ module.exports = function( grunt ) {
137
'./src/js/utils/utils.js',
148
'./src/js/utils/EventEmitter.js',
159
'./src/js/utils/DragListener.js',
16-
'./src/js/**'
10+
'./src/js/**/*.js'
1711
];
1812

19-
var basicGulpStream = function( stream ) {
20-
return stream
21-
.pipe( concat( 'goldenlayout.js' ) )
22-
.pipe( insert.wrap( '(function($){', '})(window.$);' ) );
23-
};
24-
2513
// Project configuration.
2614
grunt.initConfig( {
2715
pkg: grunt.file.readJSON( 'package.json' ),
@@ -41,7 +29,7 @@ module.exports = function( grunt ) {
4129
release: {
4230
options: {
4331
additionalFiles: [ 'bower.json' ],
44-
beforeRelease: [ 'less', 'gulp:gl', 'gulp:glmin' ],
32+
beforeRelease: [ 'less', 'concat', 'uglify' ],
4533
tagName: 'v<%= version %>',
4634
github: {
4735
repo: 'deepstreamIO/golden-layout',
@@ -50,25 +38,25 @@ module.exports = function( grunt ) {
5038
}
5139
},
5240
/***********************
53-
* GULP
41+
* CONCAT
5442
***********************/
55-
gulp: {
56-
gl: {
43+
concat: {
44+
dist: {
5745
options: {
58-
tasks: basicGulpStream
46+
banner: '(function($){',
47+
footer: '})(window.$);'
5948
},
6049
src: sources,
6150
dest: 'dist/goldenlayout.js'
62-
},
63-
glmin: {
64-
options: {
65-
tasks: function( stream ) {
66-
return basicGulpStream( stream )
67-
.pipe( uglify() )
68-
.pipe( concat( 'goldenlayout.min.js' ) );
69-
}
70-
},
71-
src: sources,
51+
}
52+
},
53+
54+
/***********************
55+
* UGLIFY
56+
***********************/
57+
uglify: {
58+
dist: {
59+
src: 'dist/goldenlayout.js',
7260
dest: 'dist/goldenlayout.min.js'
7361
}
7462
},
@@ -86,7 +74,7 @@ module.exports = function( grunt ) {
8674
travis: {
8775
configFile: 'karma.conf.js',
8876
singleRun: true,
89-
browsers: [ 'PhantomJS' ]
77+
browsers: [ 'ChromeHeadlessNoSandbox' ]
9078
}
9179
},
9280

@@ -109,11 +97,12 @@ module.exports = function( grunt ) {
10997
}
11098
);
11199

100+
grunt.loadNpmTasks( 'grunt-contrib-concat' );
112101
grunt.loadNpmTasks( 'grunt-contrib-less' );
102+
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
113103
grunt.loadNpmTasks( 'grunt-contrib-watch' );
114104
grunt.loadNpmTasks( 'grunt-release' );
115105
grunt.loadNpmTasks( 'grunt-karma' );
116-
grunt.loadNpmTasks( 'grunt-gulp' );
117106

118107
// Default task(s).
119108
grunt.registerTask( 'default', [ 'watch' ] );
@@ -122,5 +111,5 @@ module.exports = function( grunt ) {
122111
grunt.registerTask( 'test', [ 'karma:travis' ] );
123112

124113
// distribution support
125-
grunt.registerTask( 'dist', [ 'build', 'less', 'gulp' ] );
114+
grunt.registerTask( 'dist', [ 'build', 'less', 'concat', 'uglify' ] );
126115
};

0 commit comments

Comments
 (0)