diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..a880c9a
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1 @@
+prettier --check "**/*.{js,scss,html}"
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..2bcad54
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,4 @@
+{
+ "arrowParens": "always",
+ "singleQuote": true
+}
diff --git a/package-lock.json b/package-lock.json
index f6cb6a8..3124a29 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -14,8 +14,10 @@
},
"devDependencies": {
"chai": "^6.2.2",
+ "husky": "^9.1.7",
"mocha": "^11.7.5",
"normalize.css": "^8.0.1",
+ "prettier": "^3.8.1",
"sass": "^1.98.0",
"supertest": "^7.2.2"
},
@@ -1417,6 +1419,22 @@
"node": ">= 0.8"
}
},
+ "node_modules/husky": {
+ "version": "9.1.7",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
+ "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "husky": "bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -1925,6 +1943,22 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/prettier": {
+ "version": "3.8.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
+ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
diff --git a/package.json b/package.json
index baeed3a..5c72769 100644
--- a/package.json
+++ b/package.json
@@ -12,15 +12,20 @@
},
"devDependencies": {
"chai": "^6.2.2",
+ "husky": "^9.1.7",
"mocha": "^11.7.5",
"normalize.css": "^8.0.1",
+ "prettier": "^3.8.1",
"sass": "^1.98.0",
"supertest": "^7.2.2"
},
"scripts": {
"build": "sass static/scss/httpconfig.scss static/css/httpconfig.css --no-source-map --load-path=node_modules",
+ "format": "prettier --write \"**/*.{js,scss,html}\"",
+ "format:check": "prettier --check \"**/*.{js,scss,html}\"",
"start": "node httpconfig.js",
- "test": "mocha"
+ "test": "mocha",
+ "prepare": "husky"
},
"private": true,
"repository": {
diff --git a/static/html/httpconfig.html b/static/html/httpconfig.html
index 5ea1a6d..5078632 100644
--- a/static/html/httpconfig.html
+++ b/static/html/httpconfig.html
@@ -1,32 +1,48 @@
-
+
-
-
+
+
+
+
httpconfig
-
-
+
+
- httpconfig
-
+ httpconfig
+
-
+
-
+
diff --git a/static/js/httpconfig.js b/static/js/httpconfig.js
index e3640ff..49a132b 100644
--- a/static/js/httpconfig.js
+++ b/static/js/httpconfig.js
@@ -1,37 +1,51 @@
-require(['dojo/request', 'dojo/dom-construct', 'dojo/query', 'dojo/domReady!'], function(request, domConstruct, query) {
+require([
+ 'dojo/request',
+ 'dojo/dom-construct',
+ 'dojo/query',
+ 'dojo/domReady!',
+], function (request, domConstruct, query) {
+ function handleRequestSuccess(res) {
+ var container = domConstruct.create('table', { className: 'container' }),
+ key;
- function handleRequestSuccess(res) {
- var container = domConstruct.create('table', { className: 'container' }),
- key;
-
- for (key in res) {
- if (res.hasOwnProperty(key)) {
- domConstruct.create('tr', {
- className: 'result-' + key,
- innerHTML: '' + res[key].displayName + ' | ' +
- '' + (res[key].value || '') + ' | '
- }, container);
- }
- }
-
- // if (navigator.geolocation) {
- // navigator.geolocation.getCurrentPosition(function(position) {
- // domConstruct.create('tr', {
- // className: 'result-latitude',
- // innerHTML: 'Latitude | ' +
- // '' + position.coords.latitude + ' | '
- // }, container);
- // domConstruct.create('tr', {
- // className: 'result-longitude',
- // innerHTML: 'Longitude | ' +
- // '' + position.coords.longitude + ' | '
- // }, container);
- // }, function() {}, { maximumAge: 60000 });
- // }
-
- domConstruct.place(container, query('header')[0], 'after');
+ for (key in res) {
+ if (res.hasOwnProperty(key)) {
+ domConstruct.create(
+ 'tr',
+ {
+ className: 'result-' + key,
+ innerHTML:
+ '' +
+ res[key].displayName +
+ ' | ' +
+ '' +
+ (res[key].value || '') +
+ ' | ',
+ },
+ container,
+ );
+ }
}
- request.get('/api/httpconfig', { handleAs: 'json' }).then(handleRequestSuccess);
+ // if (navigator.geolocation) {
+ // navigator.geolocation.getCurrentPosition(function(position) {
+ // domConstruct.create('tr', {
+ // className: 'result-latitude',
+ // innerHTML: 'Latitude | ' +
+ // '' + position.coords.latitude + ' | '
+ // }, container);
+ // domConstruct.create('tr', {
+ // className: 'result-longitude',
+ // innerHTML: 'Longitude | ' +
+ // '' + position.coords.longitude + ' | '
+ // }, container);
+ // }, function() {}, { maximumAge: 60000 });
+ // }
+
+ domConstruct.place(container, query('header')[0], 'after');
+ }
+ request
+ .get('/api/httpconfig', { handleAs: 'json' })
+ .then(handleRequestSuccess);
});
diff --git a/static/scss/httpconfig.scss b/static/scss/httpconfig.scss
index f2eaa2e..104f9d2 100644
--- a/static/scss/httpconfig.scss
+++ b/static/scss/httpconfig.scss
@@ -1,22 +1,22 @@
@use 'normalize.css/normalize';
@mixin font-size($sizeValue, $heightValue) {
- font-size: ($sizeValue * 10) + px;
- line-height: $heightValue;
+ font-size: ($sizeValue * 10) + px;
+ line-height: $heightValue;
}
html {
- font-family: sans-serif;
- font-size: 62.5%;
- -webkit-font-smoothing: antialiased;
+ font-family: sans-serif;
+ font-size: 62.5%;
+ -webkit-font-smoothing: antialiased;
}
body {
- color: #333333;
- @include font-size(1.6, 1.5);
- margin: 0 auto;
- max-width: 700px;
- padding: 0 20px;
+ color: #333333;
+ @include font-size(1.6, 1.5);
+ margin: 0 auto;
+ max-width: 700px;
+ padding: 0 20px;
}
a {
@@ -30,80 +30,80 @@ a {
}
h1 {
- color: #999;
- @include font-size(3.2, 1.5);
- margin: 0;
- padding-top: 24px;
+ color: #999;
+ @include font-size(3.2, 1.5);
+ margin: 0;
+ padding-top: 24px;
}
hr {
- border: 0;
- border-top: 1px solid #eee;
- border-bottom: 1px solid #fff;
- margin: 24px 0;
+ border: 0;
+ border-top: 1px solid #eee;
+ border-bottom: 1px solid #fff;
+ margin: 24px 0;
- header & {
- margin-bottom: 48px;
- }
+ header & {
+ margin-bottom: 48px;
+ }
- footer & {
- margin-top: 48px;
- }
+ footer & {
+ margin-top: 48px;
+ }
}
.container {
- border: 1px solid #ddd;
- border-collapse: separate;
- border-spacing: 0;
- border-radius: 4px;
- margin: 0 auto 20px;
- width: 90%;
-
- td {
- border-top: 1px solid #ddd;
- line-height: 20px;
- padding: 8px;
- text-align: left;
- vertical-align: middle;
+ border: 1px solid #ddd;
+ border-collapse: separate;
+ border-spacing: 0;
+ border-radius: 4px;
+ margin: 0 auto 20px;
+ width: 90%;
+
+ td {
+ border-top: 1px solid #ddd;
+ line-height: 20px;
+ padding: 8px;
+ text-align: left;
+ vertical-align: middle;
+
+ &:first-child {
+ border-right: 1px solid #ddd;
+ }
+ }
+
+ tr {
+ &:first-child {
+ td {
+ border-top: 0;
&:first-child {
- border-right: 1px solid #ddd;
+ border-top-left-radius: 4px;
}
+
+ &:last-child {
+ border-top-right-radius: 4px;
+ }
+ }
}
- tr {
+ &:last-child {
+ td {
&:first-child {
- td {
- border-top: 0;
-
- &:first-child {
- border-top-left-radius: 4px;
- }
-
- &:last-child {
- border-top-right-radius: 4px;
- }
- }
+ border-bottom-left-radius: 4px;
}
&:last-child {
- td {
- &:first-child {
- border-bottom-left-radius: 4px;
- }
-
- &:last-child {
- border-bottom-right-radius: 4px;
- }
- }
+ border-bottom-right-radius: 4px;
}
+ }
+ }
- &:nth-child(odd) {
- background-color: #f9f9f9;
- }
+ &:nth-child(odd) {
+ background-color: #f9f9f9;
}
+ }
}
footer {
- text-align: center;
+ text-align: center;
}
diff --git a/test/httpconfig.test.js b/test/httpconfig.test.js
index 0fba9ef..495275d 100644
--- a/test/httpconfig.test.js
+++ b/test/httpconfig.test.js
@@ -21,7 +21,16 @@ describe('GET /api/httpconfig', function () {
it('response contains all expected fields', async function () {
const res = await request(app).get('/api/httpconfig');
- const fields = ['ip', 'hostname', 'ua', 'language', 'connection', 'encoding', 'mimeType', 'charset'];
+ const fields = [
+ 'ip',
+ 'hostname',
+ 'ua',
+ 'language',
+ 'connection',
+ 'encoding',
+ 'mimeType',
+ 'charset',
+ ];
for (const field of fields) {
expect(res.body).to.have.property(field);