@nzz/q-cli 1.5.4 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +5 -0
- package/README.md +16 -1
- package/bin/commands/bootstrap.js +6 -0
- package/dev-server/routes/rendering-info.js +0 -1
- package/dev-server/routes/tool-default.js +0 -2
- package/dev-server/server.js +3 -0
- package/package.json +1 -1
- package/skeletons/custom-code-skeleton/.nvmrc +1 -1
- package/skeletons/custom-code-skeleton/.vscode/settings.json +5 -0
- package/skeletons/custom-code-skeleton/README.md +17 -6
- package/skeletons/custom-code-skeleton/index.d.ts +3 -0
- package/skeletons/custom-code-skeleton/package-lock.json +5563 -791
- package/skeletons/custom-code-skeleton/package.json +22 -12
- package/skeletons/custom-code-skeleton/q.config.json +2 -2
- package/skeletons/custom-code-skeleton/rollup.config.js +116 -70
- package/skeletons/custom-code-skeleton/src/App.scss +5 -0
- package/skeletons/custom-code-skeleton/src/App.svelte +3 -7
- package/skeletons/custom-code-skeleton/src/interfaces.ts +0 -0
- package/skeletons/custom-code-skeleton/src/{main-prod.js → main-prod.ts} +1 -0
- package/skeletons/custom-code-skeleton/src/main.scss +1 -0
- package/skeletons/custom-code-skeleton/src/main.ts +18 -0
- package/skeletons/custom-code-skeleton/tsconfig.json +15 -0
- package/skeletons/server-skeleton/auth/routes.js +0 -9
- package/skeletons/server-skeleton/index.js +1 -3
- package/skeletons/tool-skeleton/.nvmrc +1 -1
- package/skeletons/tool-skeleton/.travis.yml +26 -0
- package/skeletons/tool-skeleton/.vscode/settings.json +5 -0
- package/skeletons/tool-skeleton/Dockerfile +1 -1
- package/skeletons/tool-skeleton/LICENSE +20 -0
- package/skeletons/tool-skeleton/README.md +1 -1
- package/skeletons/tool-skeleton/index.js +1 -6
- package/skeletons/tool-skeleton/package-lock.json +8540 -2741
- package/skeletons/tool-skeleton/package.json +24 -12
- package/skeletons/tool-skeleton/rollup.config.js +75 -0
- package/skeletons/tool-skeleton/routes/fixtures/data.js +1 -3
- package/skeletons/tool-skeleton/routes/rendering-info/web.js +43 -20
- package/skeletons/tool-skeleton/routes/routes.js +1 -1
- package/skeletons/tool-skeleton/routes/script.js +4 -5
- package/skeletons/tool-skeleton/routes/stylesheet.js +4 -5
- package/skeletons/tool-skeleton/sass.config.js +66 -0
- package/skeletons/tool-skeleton/scripts_src/default.js +3 -0
- package/skeletons/tool-skeleton/styles_src/_variables.scss +1 -0
- package/skeletons/tool-skeleton/styles_src/main.scss +2 -0
- package/skeletons/tool-skeleton/test/e2e-tests.js +4 -6
- package/skeletons/tool-skeleton/views/dynamic/YourTool.scss +5 -0
- package/skeletons/tool-skeleton/views/dynamic/YourTool.svelte +19 -0
- package/skeletons/tool-skeleton/views/static/App.scss +5 -0
- package/skeletons/tool-skeleton/views/static/App.svelte +21 -0
- package/skeletons/tool-skeleton/views/static/components/Footer.svelte +31 -0
- package/skeletons/tool-skeleton/views/static/components/Header.svelte +7 -0
- package/skeletons/custom-code-skeleton/src/main.js +0 -10
- package/skeletons/tool-skeleton/styles_src/default.scss +0 -4
- package/skeletons/tool-skeleton/tasks/build.js +0 -98
@@ -4,7 +4,10 @@
|
|
4
4
|
"description": "",
|
5
5
|
"main": "index.js",
|
6
6
|
"scripts": {
|
7
|
-
"build": "
|
7
|
+
"build": "rollup -c",
|
8
|
+
"autobuild": "rollup -c -w",
|
9
|
+
"dev": "run-p autobuild start",
|
10
|
+
"start": "nodemon index.js",
|
8
11
|
"test": "lab -a @hapi/code -c -P tests --verbose --leaks"
|
9
12
|
},
|
10
13
|
"author": "",
|
@@ -14,20 +17,29 @@
|
|
14
17
|
"url": "https://github.com/github/tool-skeleton.git"
|
15
18
|
},
|
16
19
|
"dependencies": {
|
17
|
-
"@hapi/boom": "^9.1.
|
18
|
-
"@hapi/hapi": "^20.
|
19
|
-
"@hapi/inert": "^6.0.
|
20
|
-
"ajv": "^6.
|
21
|
-
"joi": "^17.4.
|
20
|
+
"@hapi/boom": "^9.1.4",
|
21
|
+
"@hapi/hapi": "^20.2.0",
|
22
|
+
"@hapi/inert": "^6.0.4",
|
23
|
+
"ajv": "^8.6.3",
|
24
|
+
"joi": "^17.4.2",
|
25
|
+
"svelte": "^3.44.2"
|
22
26
|
},
|
23
27
|
"devDependencies": {
|
24
28
|
"@hapi/code": "^8.0.3",
|
25
|
-
"@hapi/lab": "^
|
26
|
-
"
|
27
|
-
"
|
29
|
+
"@hapi/lab": "^24.3.2",
|
30
|
+
"@rollup/plugin-commonjs": "^21.0.0",
|
31
|
+
"@rollup/plugin-node-resolve": "^13.0.5",
|
32
|
+
"autoprefixer": "^10.4.0",
|
33
|
+
"cssnano": "^5.0.10",
|
28
34
|
"glob": "^7.1.7",
|
29
|
-
"
|
30
|
-
"
|
31
|
-
"
|
35
|
+
"nodemon": "^2.0.13",
|
36
|
+
"npm-run-all": "^4.1.5",
|
37
|
+
"postcss": "^8.3.11",
|
38
|
+
"rollup": "^2.60.0",
|
39
|
+
"rollup-plugin-livereload": "^2.0.5",
|
40
|
+
"rollup-plugin-scss": "^3.0.0",
|
41
|
+
"rollup-plugin-svelte": "^7.1.0",
|
42
|
+
"rollup-plugin-terser": "^7.0.2",
|
43
|
+
"sass": "^1.43.4"
|
32
44
|
}
|
33
45
|
}
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import * as fs from "fs";
|
2
|
+
import * as path from "path";
|
3
|
+
import * as crypto from "crypto";
|
4
|
+
import nodeResolve from "@rollup/plugin-node-resolve";
|
5
|
+
import commonjs from "@rollup/plugin-commonjs";
|
6
|
+
import svelte from "rollup-plugin-svelte";
|
7
|
+
import { terser } from "rollup-plugin-terser";
|
8
|
+
import livereload from "rollup-plugin-livereload";
|
9
|
+
import scss from "rollup-plugin-scss";
|
10
|
+
const sassConfig = require("./sass.config");
|
11
|
+
|
12
|
+
const production = !process.env.ROLLUP_WATCH;
|
13
|
+
const scriptsDir = path.join(__dirname, "/scripts_src/");
|
14
|
+
const filename = "default";
|
15
|
+
const scriptDirDefaultFileName = path.join(scriptsDir, `/${filename}.js`);
|
16
|
+
|
17
|
+
function writeHashmap(hashmapPath, file, fileext) {
|
18
|
+
const hash = crypto.createHash("md5");
|
19
|
+
hash.update(file.content, { encoding: "utf8" });
|
20
|
+
file.hash = hash.digest("hex");
|
21
|
+
|
22
|
+
const hashMap = {};
|
23
|
+
hashMap[file.name] = `${file.name}.${file.hash.substring(0, 8)}.${fileext}`;
|
24
|
+
fs.writeFileSync(hashmapPath, JSON.stringify(hashMap));
|
25
|
+
}
|
26
|
+
|
27
|
+
function generateHashmap() {
|
28
|
+
return {
|
29
|
+
name: "generateHashmap",
|
30
|
+
async generateBundle(outputOptions, bundle, isWrite) {
|
31
|
+
const scriptsDir = "scripts";
|
32
|
+
// Create directory if not yet exist or recreate directory if it already exists
|
33
|
+
if (!fs.existsSync(scriptsDir)) {
|
34
|
+
fs.mkdirSync(scriptsDir);
|
35
|
+
} else {
|
36
|
+
fs.rmdirSync(scriptsDir, { recursive: true });
|
37
|
+
fs.mkdirSync(scriptsDir);
|
38
|
+
}
|
39
|
+
writeHashmap(
|
40
|
+
"scripts/hashMap.json",
|
41
|
+
{
|
42
|
+
name: filename,
|
43
|
+
content: bundle[`${filename}.js`].code,
|
44
|
+
},
|
45
|
+
"js"
|
46
|
+
);
|
47
|
+
},
|
48
|
+
};
|
49
|
+
}
|
50
|
+
|
51
|
+
export default {
|
52
|
+
input: scriptDirDefaultFileName,
|
53
|
+
output: {
|
54
|
+
format: "iife",
|
55
|
+
// TODO: Rename 'window._q_your_tool.YourTool' to 'window._q_<tool-name>.<ToolName>'
|
56
|
+
name: "window._q_your_tool.YourTool",
|
57
|
+
file: `scripts/${filename}.js`,
|
58
|
+
},
|
59
|
+
plugins: [
|
60
|
+
svelte(),
|
61
|
+
scss({ ...sassConfig.get(production, writeHashmap) }),
|
62
|
+
nodeResolve({ browser: true }),
|
63
|
+
commonjs(),
|
64
|
+
!production && livereload({ watch: ["scripts"], delay: 800 }),
|
65
|
+
production && terser(),
|
66
|
+
generateHashmap(),
|
67
|
+
],
|
68
|
+
watch: {
|
69
|
+
clearScreen: false,
|
70
|
+
},
|
71
|
+
onwarn: function (warning, warn) {
|
72
|
+
if (warning.code === "CIRCULAR_DEPENDENCY") return;
|
73
|
+
warn(warning);
|
74
|
+
},
|
75
|
+
};
|
@@ -1,7 +1,6 @@
|
|
1
1
|
const fixtureDataDirectory = "../../resources/fixtures/data";
|
2
2
|
|
3
3
|
// provide every fixture data file present in ../../resources/fixtures/data
|
4
|
-
// has to be in sync with files created in build task - see ../../tasks/build.js
|
5
4
|
const fixtureData = [require(`${fixtureDataDirectory}/basic.json`)];
|
6
5
|
|
7
6
|
module.exports = {
|
@@ -9,9 +8,8 @@ module.exports = {
|
|
9
8
|
method: "GET",
|
10
9
|
options: {
|
11
10
|
tags: ["api"],
|
12
|
-
cors: true
|
13
11
|
},
|
14
12
|
handler: (request, h) => {
|
15
13
|
return fixtureData;
|
16
|
-
}
|
14
|
+
},
|
17
15
|
};
|
@@ -1,21 +1,32 @@
|
|
1
1
|
const Boom = require("@hapi/boom");
|
2
2
|
const fs = require("fs");
|
3
3
|
const path = require("path");
|
4
|
+
const Ajv = require("ajv");
|
4
5
|
|
6
|
+
const staticViewsDir = path.join(__dirname, "/../../views/static/");
|
5
7
|
const stylesDir = path.join(__dirname, "/../../styles/");
|
8
|
+
const scriptsDir = path.join(__dirname, "../../scripts/");
|
9
|
+
|
10
|
+
require("svelte/register");
|
11
|
+
const staticTemplate = require(path.join(
|
12
|
+
staticViewsDir,
|
13
|
+
"/App.svelte"
|
14
|
+
)).default;
|
15
|
+
const styles = fs.readFileSync(path.join(stylesDir, "/default.css")).toString();
|
6
16
|
const styleHashMap = require(path.join(stylesDir, "hashMap.json"));
|
17
|
+
const scriptHashMap = require(path.join(scriptsDir, "hashMap.json"));
|
7
18
|
|
8
19
|
// POSTed item will be validated against given schema
|
9
20
|
// hence we fetch the JSON schema...
|
10
21
|
const schemaString = JSON.parse(
|
11
22
|
fs.readFileSync(path.join(__dirname, "../../resources/", "schema.json"), {
|
12
|
-
encoding: "utf-8"
|
23
|
+
encoding: "utf-8",
|
13
24
|
})
|
14
25
|
);
|
15
|
-
const Ajv = require("ajv");
|
16
|
-
const ajv = new Ajv();
|
17
26
|
|
27
|
+
const ajv = new Ajv({ strict: false });
|
18
28
|
const validate = ajv.compile(schemaString);
|
29
|
+
|
19
30
|
function validateAgainstSchema(item, options) {
|
20
31
|
if (validate(item)) {
|
21
32
|
return item;
|
@@ -43,32 +54,44 @@ module.exports = {
|
|
43
54
|
options: {
|
44
55
|
validate: {
|
45
56
|
options: {
|
46
|
-
allowUnknown: true
|
57
|
+
allowUnknown: true,
|
47
58
|
},
|
48
|
-
payload: validatePayload
|
49
|
-
}
|
59
|
+
payload: validatePayload,
|
60
|
+
},
|
50
61
|
},
|
51
|
-
handler: async function(request, h) {
|
52
|
-
const
|
62
|
+
handler: async function (request, h) {
|
63
|
+
const toolRuntimeConfig = request.payload.toolRuntimeConfig;
|
64
|
+
const context = {
|
65
|
+
// TODO: Rename 'q_your_tool_' to 'q_<tool_name>_'
|
66
|
+
id: `q_your_tool_${toolRuntimeConfig.requestId}`,
|
67
|
+
displayOptions: toolRuntimeConfig.displayOptions || {},
|
68
|
+
item: request.payload.item,
|
69
|
+
};
|
70
|
+
|
71
|
+
const staticTemplateRender = staticTemplate.render(context);
|
53
72
|
|
54
73
|
const renderingInfo = {
|
55
74
|
polyfills: ["Promise"],
|
56
|
-
stylesheets: [
|
57
|
-
{
|
58
|
-
name: styleHashMap["default"]
|
59
|
-
}
|
60
|
-
],
|
75
|
+
stylesheets: [{ content: styles }, { name: styleHashMap["default"] }],
|
61
76
|
scripts: [
|
77
|
+
{ name: scriptHashMap["default"] },
|
78
|
+
// TODO: Rename 'new window._q_your_tool.YourTool' to 'new window._q_<tool-name>.<ToolName>'
|
62
79
|
{
|
63
|
-
content:
|
64
|
-
|
65
|
-
|
80
|
+
content: `
|
81
|
+
(function () {
|
82
|
+
var target = document.querySelector('#${context.id}_container');
|
83
|
+
target.innerHTML = "";
|
84
|
+
var props = ${JSON.stringify(context)};
|
85
|
+
new window._q_your_tool.YourTool({
|
86
|
+
"target": target,
|
87
|
+
"props": props
|
88
|
+
})
|
89
|
+
})();`,
|
90
|
+
},
|
66
91
|
],
|
67
|
-
markup:
|
68
|
-
item.subtitle
|
69
|
-
}</h2><p>rendered by tool-skeleton`
|
92
|
+
markup: staticTemplateRender.html,
|
70
93
|
};
|
71
94
|
|
72
95
|
return renderingInfo;
|
73
|
-
}
|
96
|
+
},
|
74
97
|
};
|
@@ -4,15 +4,14 @@ module.exports = {
|
|
4
4
|
method: "GET",
|
5
5
|
path: "/script/{filename}.{hash}.{extension}",
|
6
6
|
options: {
|
7
|
-
cors: true,
|
8
7
|
files: {
|
9
|
-
relativeTo: path.join(__dirname, "/../scripts/")
|
10
|
-
}
|
8
|
+
relativeTo: path.join(__dirname, "/../scripts/"),
|
9
|
+
},
|
11
10
|
},
|
12
|
-
handler: function(request, h) {
|
11
|
+
handler: function (request, h) {
|
13
12
|
return h
|
14
13
|
.file(`${request.params.filename}.${request.params.extension}`)
|
15
14
|
.type("text/javascript")
|
16
15
|
.header("cache-control", `max-age=${60 * 60 * 24 * 365}, immutable`); // 1 year
|
17
|
-
}
|
16
|
+
},
|
18
17
|
};
|
@@ -4,15 +4,14 @@ module.exports = {
|
|
4
4
|
method: "GET",
|
5
5
|
path: "/stylesheet/{filename}.{hash}.{extension}",
|
6
6
|
options: {
|
7
|
-
cors: true,
|
8
7
|
files: {
|
9
|
-
relativeTo: path.join(__dirname, "/../styles/")
|
10
|
-
}
|
8
|
+
relativeTo: path.join(__dirname, "/../styles/"),
|
9
|
+
},
|
11
10
|
},
|
12
|
-
handler: function(request, h) {
|
11
|
+
handler: function (request, h) {
|
13
12
|
return h
|
14
13
|
.file(`${request.params.filename}.${request.params.extension}`)
|
15
14
|
.type("text/css")
|
16
15
|
.header("cache-control", `max-age=${60 * 60 * 24 * 365}, immutable`); // 1 year
|
17
|
-
}
|
16
|
+
},
|
18
17
|
};
|
@@ -0,0 +1,66 @@
|
|
1
|
+
const fs = require("fs");
|
2
|
+
const path = require("path");
|
3
|
+
const postcss = require("postcss");
|
4
|
+
const autoprefixer = require("autoprefixer");
|
5
|
+
const cssnano = require("cssnano");
|
6
|
+
|
7
|
+
function createOutputCssFunction(writeHashmapFunction) {
|
8
|
+
const outputCssFunction = (styles, styleNodes) => {
|
9
|
+
const stylesDir = "styles";
|
10
|
+
|
11
|
+
if (!fs.existsSync(stylesDir)) {
|
12
|
+
fs.mkdirSync(stylesDir);
|
13
|
+
}
|
14
|
+
|
15
|
+
fs.writeFileSync(`styles/default.css`, styles);
|
16
|
+
writeHashmapFunction(
|
17
|
+
"styles/hashMap.json",
|
18
|
+
{
|
19
|
+
name: "default",
|
20
|
+
content: styles,
|
21
|
+
},
|
22
|
+
"css"
|
23
|
+
);
|
24
|
+
};
|
25
|
+
|
26
|
+
return outputCssFunction;
|
27
|
+
}
|
28
|
+
|
29
|
+
function getPostcssPlugins(isProduction) {
|
30
|
+
const postcssPlugins = [autoprefixer];
|
31
|
+
|
32
|
+
if (isProduction) {
|
33
|
+
postcssPlugins.push(cssnano);
|
34
|
+
}
|
35
|
+
|
36
|
+
return postcssPlugins;
|
37
|
+
}
|
38
|
+
|
39
|
+
function get(isProduction, writeHashmapFunction) {
|
40
|
+
const config = {
|
41
|
+
outputStyle: isProduction ? "compressed" : "expanded",
|
42
|
+
// Sourcemap generation (specifically writing the file to system) is currently not supported by rollup-plugin-sass (but soon!)
|
43
|
+
// See: https://github.com/thgh/rollup-plugin-scss/issues/7
|
44
|
+
// outFile: path.join(__dirname, "/styles/default.css"), // <- Uncomment after: https://github.com/thgh/rollup-plugin-scss/issues/7
|
45
|
+
sourceMap: !isProduction,
|
46
|
+
sourceMapEmbed: !isProduction, // Remove after: https://github.com/thgh/rollup-plugin-scss/issues/7
|
47
|
+
failOnError: !isProduction,
|
48
|
+
watch: [
|
49
|
+
path.join(__dirname, "/styles_src"),
|
50
|
+
path.join(__dirname, "/views"),
|
51
|
+
],
|
52
|
+
processor: (css) =>
|
53
|
+
postcss(getPostcssPlugins(isProduction))
|
54
|
+
.process(css, {
|
55
|
+
from: path.join(__dirname, "/styles/default.css"),
|
56
|
+
to: path.join(__dirname, "/styles/default.css"),
|
57
|
+
map: isProduction ? false : { inline: true }, // Set to false after: https://github.com/thgh/rollup-plugin-scss/issues/7
|
58
|
+
})
|
59
|
+
.then((result) => result.css),
|
60
|
+
output: createOutputCssFunction(writeHashmapFunction),
|
61
|
+
};
|
62
|
+
|
63
|
+
return config;
|
64
|
+
}
|
65
|
+
|
66
|
+
module.exports = { get };
|
@@ -0,0 +1 @@
|
|
1
|
+
$color: salmon;
|
@@ -20,9 +20,7 @@ before(async () => {
|
|
20
20
|
try {
|
21
21
|
server = Hapi.server({
|
22
22
|
port: process.env.PORT || 3000,
|
23
|
-
routes: {
|
24
|
-
cors: true,
|
25
|
-
},
|
23
|
+
routes: {},
|
26
24
|
});
|
27
25
|
server.validator(Joi);
|
28
26
|
await server.register(require("@hapi/inert"));
|
@@ -103,7 +101,7 @@ lab.experiment("stylesheets endpoint", () => {
|
|
103
101
|
});
|
104
102
|
|
105
103
|
// all the fixtures render
|
106
|
-
lab.experiment("all fixtures render",
|
104
|
+
lab.experiment("all fixtures render", () => {
|
107
105
|
const fixtureFiles = glob.sync(
|
108
106
|
`${__dirname}/../resources/fixtures/data/*.json`
|
109
107
|
);
|
@@ -143,7 +141,7 @@ lab.experiment("rendering-info", () => {
|
|
143
141
|
});
|
144
142
|
|
145
143
|
lab.experiment("assets", () => {
|
146
|
-
it("
|
144
|
+
it("returns stylesheet", async () => {
|
147
145
|
const fixture = fs.readFileSync(
|
148
146
|
`${__dirname}/../resources/fixtures/data/basic.json`,
|
149
147
|
{ encoding: "utf-8" }
|
@@ -157,7 +155,7 @@ lab.experiment("assets", () => {
|
|
157
155
|
},
|
158
156
|
});
|
159
157
|
const stylesheetRes = await server.inject(
|
160
|
-
`/stylesheet/${res.result.stylesheets[
|
158
|
+
`/stylesheet/${res.result.stylesheets[1].name}`
|
161
159
|
);
|
162
160
|
expect(stylesheetRes.statusCode).to.be.equal(200);
|
163
161
|
});
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<script>
|
2
|
+
// TODO: Rename 'YourTool.svelte' to '<Tool-Name>.svelte' & change all references
|
3
|
+
let isWorkingLabel = "";
|
4
|
+
let i = 0;
|
5
|
+
|
6
|
+
function worksOnClick() {
|
7
|
+
i++;
|
8
|
+
isWorkingLabel = i < 5 ? "is working!" : "is still working!";
|
9
|
+
}
|
10
|
+
</script>
|
11
|
+
|
12
|
+
<!-- Client side code is written/imported inside this component (e.g. Client interaction components) -->
|
13
|
+
<div class="s-font-title">
|
14
|
+
Client-Side code
|
15
|
+
<span class="your-tool__is-working-label">{isWorkingLabel}</span>
|
16
|
+
</div>
|
17
|
+
<button class="s-button s-button--small" on:click={worksOnClick}>
|
18
|
+
Click me!
|
19
|
+
</button>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<script>
|
2
|
+
import Header from "./components/Header.svelte";
|
3
|
+
import Footer from "./components/Footer.svelte";
|
4
|
+
|
5
|
+
export let item;
|
6
|
+
export let id;
|
7
|
+
export let displayOptions;
|
8
|
+
</script>
|
9
|
+
|
10
|
+
<!-- Static code is written/imported inside 'q-item-container' (e.g. Header, Title components) -->
|
11
|
+
<div class="q-item-container">
|
12
|
+
{#if !displayOptions.hideTitle}
|
13
|
+
<Header title={item.title} />
|
14
|
+
{#if item.subtitle}
|
15
|
+
<div class="s-q-item__subtitle s-font-note">{item.subtitle}</div>
|
16
|
+
{/if}
|
17
|
+
{/if}
|
18
|
+
<!-- TODO: Rename 'q-your-tool-container' to 'q-<tool-name>-container' & change all references -->
|
19
|
+
<div id="{id}_container" class="q-your-tool-container" />
|
20
|
+
<Footer notes={item.notes} sources={item.sources} acronym={item.acronym} />
|
21
|
+
</div>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<script>
|
2
|
+
export let notes;
|
3
|
+
export let sources;
|
4
|
+
export let acronym;
|
5
|
+
</script>
|
6
|
+
|
7
|
+
<div class="s-q-item__footer">
|
8
|
+
{#if notes}
|
9
|
+
<div class="s-q-item__footer__notes">{notes}</div>
|
10
|
+
{/if}
|
11
|
+
<div class="s-q-item__footer__details">
|
12
|
+
{#if sources && sources.length > 0}
|
13
|
+
<div class="s-q-item__footer__sources">
|
14
|
+
{#if sources.length > 1}Quellen:{:else}Quelle:{/if}
|
15
|
+
{#each sources as source, index}
|
16
|
+
{#if source.text !== ""}
|
17
|
+
{#if source.link && source.link.url && source.link.isValid}<a
|
18
|
+
href={source.link.url}
|
19
|
+
target="blank"
|
20
|
+
rel="noopener noreferrer">{source.text}</a
|
21
|
+
>{:else}{source.text}{/if}{#if index !== sources.length - 1 && sources[index + 1] !== ""}, {/if}{/if}
|
22
|
+
{/each}
|
23
|
+
</div>
|
24
|
+
{/if}
|
25
|
+
{#if acronym}
|
26
|
+
<div class="s-q-item__footer__acronym">NZZ / {acronym}</div>
|
27
|
+
{:else}
|
28
|
+
<div class="s-q-item__footer__acronym">NZZ</div>
|
29
|
+
{/if}
|
30
|
+
</div>
|
31
|
+
</div>
|
@@ -1,98 +0,0 @@
|
|
1
|
-
const fs = require("fs");
|
2
|
-
const path = require("path");
|
3
|
-
const crypto = require("crypto");
|
4
|
-
|
5
|
-
const sass = require("sass");
|
6
|
-
const postcss = require("postcss");
|
7
|
-
const postcssImport = require("postcss-import");
|
8
|
-
const autoprefixer = require("autoprefixer");
|
9
|
-
const cssnano = require("cssnano");
|
10
|
-
|
11
|
-
const stylesDir = path.join(__dirname, "/../styles_src/");
|
12
|
-
|
13
|
-
function writeHashmap(hashmapPath, files, fileext) {
|
14
|
-
const hashMap = {};
|
15
|
-
files
|
16
|
-
.map(file => {
|
17
|
-
const hash = crypto.createHash("md5");
|
18
|
-
hash.update(file.content, { encoding: "utf8" });
|
19
|
-
file.hash = hash.digest("hex");
|
20
|
-
return file;
|
21
|
-
})
|
22
|
-
.map(file => {
|
23
|
-
hashMap[file.name] = `${file.name}.${file.hash.substring(
|
24
|
-
0,
|
25
|
-
8
|
26
|
-
)}.${fileext}`;
|
27
|
-
});
|
28
|
-
|
29
|
-
fs.writeFileSync(hashmapPath, JSON.stringify(hashMap));
|
30
|
-
}
|
31
|
-
|
32
|
-
async function compileStylesheet(name) {
|
33
|
-
return new Promise((resolve, reject) => {
|
34
|
-
const filePath = path.join(stylesDir, `${name}.scss`);
|
35
|
-
fs.access(filePath, fs.constants.R_OK, err => {
|
36
|
-
if (err) {
|
37
|
-
reject(new Error(`stylesheet ${filePath} cannot be read`));
|
38
|
-
process.exit(1);
|
39
|
-
}
|
40
|
-
sass.render(
|
41
|
-
{
|
42
|
-
file: filePath,
|
43
|
-
outputStyle: "compressed"
|
44
|
-
},
|
45
|
-
(err, sassResult) => {
|
46
|
-
if (err) {
|
47
|
-
reject(err);
|
48
|
-
} else {
|
49
|
-
postcss()
|
50
|
-
.use(postcssImport)
|
51
|
-
.use(autoprefixer)
|
52
|
-
.use(cssnano)
|
53
|
-
.process(sassResult.css, {
|
54
|
-
from: path.join(stylesDir, `${name}.css`)
|
55
|
-
})
|
56
|
-
.then(prefixedResult => {
|
57
|
-
if (prefixedResult.warnings().length > 0) {
|
58
|
-
console.log(`failed to compile stylesheet ${name}`);
|
59
|
-
process.exit(1);
|
60
|
-
}
|
61
|
-
resolve(prefixedResult.css);
|
62
|
-
});
|
63
|
-
}
|
64
|
-
}
|
65
|
-
);
|
66
|
-
});
|
67
|
-
});
|
68
|
-
}
|
69
|
-
|
70
|
-
async function buildStyles() {
|
71
|
-
try {
|
72
|
-
// compile styles
|
73
|
-
const styleFiles = [
|
74
|
-
{
|
75
|
-
name: "default",
|
76
|
-
content: await compileStylesheet("default")
|
77
|
-
}
|
78
|
-
];
|
79
|
-
|
80
|
-
styleFiles.map(file => {
|
81
|
-
fs.writeFileSync(`styles/${file.name}.css`, file.content);
|
82
|
-
});
|
83
|
-
|
84
|
-
writeHashmap("styles/hashMap.json", styleFiles, "css");
|
85
|
-
} catch (err) {
|
86
|
-
console.error(err);
|
87
|
-
process.exit(1);
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
Promise.all([buildStyles()])
|
92
|
-
.then(res => {
|
93
|
-
console.log("build complete");
|
94
|
-
})
|
95
|
-
.catch(err => {
|
96
|
-
console.error(err.message);
|
97
|
-
process.exit(1);
|
98
|
-
});
|