diff --git a/README.md b/README.md index 618909af..aaecb767 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,9 @@ # How-to? * [Get access rights](https://github.com/hestiaAI/website.docs/tree/main/website-access-rights) — _would you need _editorial access_ to the website contents; or to _administer_ our Netlify deployment & hosting infrastructure_ +* [Setup your dev environment](https://github.com/hestiaAI/website.docs/tree/main/website-dev-setup) — _develop features of the website, install prequisite tools and dependencies and start the dev server_ * [Execute the dev, build and deployment sequences](https://github.com/hestiaAI/website.docs/tree/main/website-execution) — _understand the execution modes, environments and how-to execute the dev, build and deployment sequences_ -* [Contribute to codebase](https://github.com/hestiaAI/website.docs/tree/main/website-contrib) — _Design decisions you should know about and how-to submit code changes_ +* [Contribute to codebase](https://github.com/hestiaAI/website.docs/tree/main/website-contrib) — _design decisions you should know about and how-to submit code changes_ # Repository contents diff --git a/conf/netlify/cms/config.yml b/conf/netlify/cms/config.yml index 93279ab0..eda64423 100644 --- a/conf/netlify/cms/config.yml +++ b/conf/netlify/cms/config.yml @@ -170,42 +170,48 @@ collections: - { label: "Partners link text", name: partners_link_text, required: false, widget: string, i18n: true } - { label: "News title", name: news_title, required: false, i18n: true, widget: markdown, buttons: [bold, italic, link], editor_components: [], minimal: true} - - label: "News editorials" - name: "news_editorials" + - label: "News" + name: "news" widget: "list" i18n: true - field: - name: "Editorial" - widget: relation - collection: editorials - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "News interviews" - name: "news_interviews" - widget: "list" - i18n: true - field: - name: "Interview" - widget: relation - collection: interviews - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "News infographics" - name: "news_infographics" - widget: "list" - i18n: true - field: - name: "Infographic" - widget: relation - collection: infographics - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] + max: 3 + types: + - label: "Editorial" + name: "editorial" + summary: '{{fields.editorial}}' + fields: + - label: Editorial + name: "editorial" + widget: relation + collection: editorials + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Interview" + name: "interview" + summary: '{{fields.interview}}' + fields: + - label: Interview + name: "interview" + widget: relation + collection: interviews + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Infographic" + name: "infographic" + summary: '{{fields.infographic}}' + fields: + - label: Infographic + name: "infographic" + widget: relation + collection: infographics + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] - label: Community name: community @@ -460,42 +466,47 @@ collections: value_field: "id" multiple: true search_fields: ["name", "id", "description"] - - label: "Suggested editorials" - name: "suggested_editorials" + - label: "Suggested" + name: "suggested" widget: "list" i18n: true - field: - name: "Editorial" - widget: relation - collection: editorials - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested interviews" - name: "suggested_interviews" - widget: "list" - i18n: true - field: - name: "Interview" - widget: relation - collection: interviews - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested infographics" - name: "suggested_infographics" - widget: "list" - i18n: true - field: - name: "Infographic" - widget: relation - collection: infographics - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] + types: + - label: "Editorial" + name: "editorial" + summary: '{{fields.editorial}}' + fields: + - label: Editorial + name: "editorial" + widget: relation + collection: editorials + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Interview" + name: "interview" + summary: '{{fields.interview}}' + fields: + - label: Interview + name: "interview" + widget: relation + collection: interviews + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Infographic" + name: "infographic" + summary: '{{fields.infographic}}' + fields: + - label: Infographic + name: "infographic" + widget: relation + collection: infographics + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] - { label: "Show social media sharing", name: show_social_sharing, required: false, widget: boolean, i18n: true } - label: Blog › Interviews @@ -534,42 +545,47 @@ collections: value_field: "id" multiple: true search_fields: ["name", "id", "description"] - - label: "Suggested editorials" - name: "suggested_editorials" + - label: "Suggested" + name: "suggested" widget: "list" i18n: true - field: - name: "Editorial" - widget: relation - collection: editorials - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested interviews" - name: "suggested_interviews" - widget: "list" - i18n: true - field: - name: "Interview" - widget: relation - collection: interviews - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested infographics" - name: "suggested_infographics" - widget: "list" - i18n: true - field: - name: "Infographic" - widget: relation - collection: infographics - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] + types: + - label: "Editorial" + name: "editorial" + summary: '{{fields.editorial}}' + fields: + - label: Editorial + name: "editorial" + widget: relation + collection: editorials + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Interview" + name: "interview" + summary: '{{fields.interview}}' + fields: + - label: Interview + name: "interview" + widget: relation + collection: interviews + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Infographic" + name: "infographic" + summary: '{{fields.infographic}}' + fields: + - label: Infographic + name: "infographic" + widget: relation + collection: infographics + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] - { label: "Show social media sharing", name: show_social_sharing, required: false, widget: boolean, i18n: true } - label: Blog › Infographics @@ -607,42 +623,47 @@ collections: value_field: "id" multiple: true search_fields: ["name", "id", "description"] - - label: "Suggested editorials" - name: "suggested_editorials" + - label: "Suggested" + name: "suggested" widget: "list" i18n: true - field: - name: "Editorial" - widget: relation - collection: editorials - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested interviews" - name: "suggested_interviews" - widget: "list" - i18n: true - field: - name: "Interview" - widget: relation - collection: interviews - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] - - label: "Suggested infographics" - name: "suggested_infographics" - widget: "list" - i18n: true - field: - name: "Infographic" - widget: relation - collection: infographics - value_field: "id" - display_fields: ["title"] - multiple: false - search_fields: ["title", "body"] + types: + - label: "Editorial" + name: "editorial" + summary: '{{fields.editorial}}' + fields: + - label: Editorial + name: "editorial" + widget: relation + collection: editorials + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Interview" + name: "interview" + summary: '{{fields.interview}}' + fields: + - label: Interview + name: "interview" + widget: relation + collection: interviews + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] + - label: "Infographic" + name: "infographic" + summary: '{{fields.infographic}}' + fields: + - label: Infographic + name: "infographic" + widget: relation + collection: infographics + value_field: "id" + display_fields: ["title"] + multiple: false + search_fields: ["title", "body"] - { label: "Show social media sharing", name: show_social_sharing, required: false, widget: boolean, i18n: true } - label: Blog › Categories diff --git a/package-lock.json b/package-lock.json index 92bb2ef3..c0f0d715 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,8 +20,11 @@ "markdown-it-plain-text": "^0.2.1", "netlify-cms-proxy-server": "^1.3.12", "npm-run-all": "^4.1.5", + "prompts": "^2.4.1", + "replace-in-file": "^6.2.0", "rimraf": "^3.0.2", - "snowpack": "^3.5.2" + "snowpack": "^3.5.2", + "winston": "^3.3.3" }, "engines": { "node": ">=14", @@ -3413,6 +3416,15 @@ "node": ">=0.10.0" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -5019,6 +5031,19 @@ "node": ">=10" } }, + "node_modules/prompts": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", + "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -5335,6 +5360,131 @@ "node": ">=0.10.0" } }, + "node_modules/replace-in-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.2.0.tgz", + "integrity": "sha512-Im2AF9G/qgkYneOc9QwWwUS/efyyonTUBvzXS2VXuxPawE5yQIjT/e6x4CTijO0Quq48lfAujuo+S89RR2TP2Q==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "glob": "^7.1.6", + "yargs": "^16.2.0" + }, + "bin": { + "replace-in-file": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/replace-in-file/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-in-file/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/replace-in-file/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-in-file/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-in-file/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-in-file/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/replace-in-file/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/replace-in-file/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/replace-in-file/node_modules/yargs-parser": { + "version": "20.2.7", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", + "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -5837,6 +5987,12 @@ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", "dev": true }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -9774,6 +9930,12 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "kuler": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", @@ -11032,6 +11194,16 @@ "retry": "^0.12.0" } }, + "prompts": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", + "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", @@ -11306,6 +11478,100 @@ } } }, + "replace-in-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-6.2.0.tgz", + "integrity": "sha512-Im2AF9G/qgkYneOc9QwWwUS/efyyonTUBvzXS2VXuxPawE5yQIjT/e6x4CTijO0Quq48lfAujuo+S89RR2TP2Q==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "glob": "^7.1.6", + "yargs": "^16.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.7", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", + "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "dev": true + } + } + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -11723,6 +11989,12 @@ } } }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", diff --git a/package.json b/package.json index c5c97244..1a388ef2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@hestia/website-showcase", "version": "0.1.0", - "description": "HestiaLabs Your Showcase website", + "description": "HestiaLabs ‹Your Showcase› website", "license": "UNLICENSED", "author": "Andréas Kündig", "contributors": [ @@ -15,6 +15,7 @@ "access": "restricted" }, "scripts": { + "setup-post-fork": "node tools/setup-post-fork.js", "postinstall": "npm dedupe", "clean": "rimraf build", "prebuild": "npm run clean", @@ -40,8 +41,11 @@ "markdown-it-plain-text": "^0.2.1", "netlify-cms-proxy-server": "^1.3.12", "npm-run-all": "^4.1.5", + "prompts": "^2.4.1", + "replace-in-file": "^6.2.0", "rimraf": "^3.0.2", - "snowpack": "^3.5.2" + "snowpack": "^3.5.2", + "winston": "^3.3.3" }, "engines": { "node": ">=14", diff --git a/src/site/_layouts/home.html b/src/site/_layouts/home.html index 099d2a4a..95f85ebf 100644 --- a/src/site/_layouts/home.html +++ b/src/site/_layouts/home.html @@ -27,31 +27,30 @@

{% inlineMarkdown partners_title %}

-
-

{% inlineMarkdown news_title %}

- -
- {% set news = {editorial: news_editorials, - interview: news_interviews, - infographic: news_infographics} %} - {% for news_type, news_ids in news %} - {% for edito in collections[news_type] %} - {% if edito.data.locale == locale and news_ids - and edito.data.id in news_ids %} +{% if news | length %} +
+

{% inlineMarkdown news_title %}

+ +
+ {% for item in news %} + {% set newsId = item[item.type] %} + {% for post in collections[item.type] %} + {% if post.data.locale == locale and post.data.id == newsId %} - {% inlineMarkdown edito.data.image_caption %} -

{% inlineMarkdown edito.data.title %}

- {% markdown edito.data.lead %} + href="{{post.url | url}}" img-src="{{post.data.image | url}}"> + {% inlineMarkdown post.data.image_caption %} +

{% inlineMarkdown post.data.title %}

+ {% markdown post.data.lead %}
{% endif %} {% endfor %} {% endfor %} -
-
+
+
+{% endif %}
-
-

{% inlineMarkdown i18n.globals[locale].suggested_posts_title %}

- {% set suggested_posts = [].concat(suggested_editorials, suggested_interviews, suggested_infographics) %} - {% for post in collections.post %} - {% if post.data.locale == locale and post.data.id in suggested_posts %} -

{% inlineMarkdown post.data.title %}

- {% endif %} - {% endfor %} -
+{% if suggested | length %} +
+

{% inlineMarkdown i18n.globals[locale].suggested_posts_title %}

+ {% for item in suggested %} + {% for post in collections[item.type] %} + {% set newsId = item[item.type] %} + {% if post.data.locale == locale and post.data.id == newsId %} +

+ {% inlineMarkdown post.data.title %}

+ {% endif %} + {% endfor %} + {% endfor %} +
+{% endif %} {% if show_social_sharing %} -
- {% include "share.njk" %} -
+
+ {% include "share.njk" %} +
{% endif %}
diff --git a/src/site/_layouts/post.html b/src/site/_layouts/post.html index f725c8ff..9cfecaad 100644 --- a/src/site/_layouts/post.html +++ b/src/site/_layouts/post.html @@ -28,20 +28,25 @@
-
-

{% inlineMarkdown i18n.globals[locale].suggested_posts_title %}

- {% set suggested_posts = [].concat(suggested_editorials, suggested_interviews, suggested_infographics) %} - {% for post in collections.post %} - {% if post.data.locale == locale and post.data.id in suggested_posts %} -

{% inlineMarkdown post.data.title %}

- {% endif %} - {% endfor %} -
+{% if suggested | length %} +
+

{% inlineMarkdown i18n.globals[locale].suggested_posts_title %}

+ {% for item in suggested %} + {% for post in collections[item.type] %} + {% set newsId = item[item.type] %} + {% if post.data.locale == locale and post.data.id == newsId %} +

+ {% inlineMarkdown post.data.title %}

+ {% endif %} + {% endfor %} + {% endfor %} +
+{% endif %} {% if show_social_sharing %} -
- {% include "share.njk" %} -
+
+ {% include "share.njk" %} +
{% endif %}
diff --git a/src/site/blog/editorial/en/dating-apps-share-your-data.md b/src/site/blog/editorial/en/dating-apps-share-your-data.md index d6d91d6f..4de8636a 100644 --- a/src/site/blog/editorial/en/dating-apps-share-your-data.md +++ b/src/site/blog/editorial/en/dating-apps-share-your-data.md @@ -9,8 +9,9 @@ post_categories: - worth-reading post_authors: - mpv -suggested_editorials: - - interview-de-jessica-pidoux-journal-le-temps +suggested: + - type: interview + interview: interview-de-jessica-pidoux-journal-le-temps --- In this [report «Out Of Control»](https://www.forbrukerradet.no/undersokelse/no-undersokelsekategori/report-out-of-control/) published in January 2020, Norwegian Consumer Council demonstrate how every time we use our phones, a large number of shadowy entities that are virtually unknown to consumers are receiving personal data about our interests, habits, and behavior. diff --git a/src/site/blog/editorial/fr/dating-apps-share-your-data.md b/src/site/blog/editorial/fr/dating-apps-share-your-data.md index d6d91d6f..4de8636a 100644 --- a/src/site/blog/editorial/fr/dating-apps-share-your-data.md +++ b/src/site/blog/editorial/fr/dating-apps-share-your-data.md @@ -9,8 +9,9 @@ post_categories: - worth-reading post_authors: - mpv -suggested_editorials: - - interview-de-jessica-pidoux-journal-le-temps +suggested: + - type: interview + interview: interview-de-jessica-pidoux-journal-le-temps --- In this [report «Out Of Control»](https://www.forbrukerradet.no/undersokelse/no-undersokelsekategori/report-out-of-control/) published in January 2020, Norwegian Consumer Council demonstrate how every time we use our phones, a large number of shadowy entities that are virtually unknown to consumers are receiving personal data about our interests, habits, and behavior. diff --git a/src/site/blog/interview/en/interview-de-jessica-pidoux-journal-le-temps.md b/src/site/blog/interview/en/interview-de-jessica-pidoux-journal-le-temps.md index dd4e3118..d000d7aa 100644 --- a/src/site/blog/interview/en/interview-de-jessica-pidoux-journal-le-temps.md +++ b/src/site/blog/interview/en/interview-de-jessica-pidoux-journal-le-temps.md @@ -8,8 +8,9 @@ post_categories: - news post_authors: - mpv -suggested_editorials: - - dating-apps-share-your-data +suggested: + - type: editorial + editorial: dating-apps-share-your-data --- [Jessica Pidoux, l'algorithme de Tinder dans la peau](https://www.letemps.ch/societe/jessica-pidoux-lalgorithme-tinder-peau) \ - by Florian Delafoi, published on 24 February 2020 in the Swiss newspaper «Le Temps». \ No newline at end of file + by Florian Delafoi, published on 24 February 2020 in the Swiss newspaper «Le Temps». diff --git a/src/site/blog/interview/fr/interview-de-jessica-pidoux-journal-le-temps.md b/src/site/blog/interview/fr/interview-de-jessica-pidoux-journal-le-temps.md index 1fdc7de2..bdcee762 100644 --- a/src/site/blog/interview/fr/interview-de-jessica-pidoux-journal-le-temps.md +++ b/src/site/blog/interview/fr/interview-de-jessica-pidoux-journal-le-temps.md @@ -8,8 +8,9 @@ post_categories: - news post_authors: - mpv -suggested_editorials: - - dating-apps-share-your-data +suggested: + - type: editorial + editorial: dating-apps-share-your-data --- [Jessica Pidoux, l'algorithme de Tinder dans la peau](https://www.letemps.ch/societe/jessica-pidoux-lalgorithme-tinder-peau) \ - par Florian Delafoi, publié le 24 février 2020 dans le journal suisse «Le Temps». \ No newline at end of file + par Florian Delafoi, publié le 24 février 2020 dans le journal suisse «Le Temps». diff --git a/src/site/home/en/index.md b/src/site/home/en/index.md index 353c907f..411fb37e 100644 --- a/src/site/home/en/index.md +++ b/src/site/home/en/index.md @@ -36,8 +36,11 @@ permalink: /en/index.html mission_link_text: Learn more partners_link_text: Contact us news_title: News and events -news_editorials: - - dating-apps-share-your-data -news_interviews: - - interview-de-jessica-pidoux-journal-le-temps +news: + - type: infographic + infographic: what-bumble-collects-about-you + - type: editorial + editorial: dating-apps-share-your-data + - type: interview + interview: interview-de-jessica-pidoux-journal-le-temps --- diff --git a/src/site/home/fr/index.md b/src/site/home/fr/index.md index 861813dd..2b8d3cdc 100644 --- a/src/site/home/fr/index.md +++ b/src/site/home/fr/index.md @@ -36,8 +36,11 @@ permalink: /fr/index.html mission_link_text: Learn more partners_link_text: Contact us news_title: News and events -news_editorials: - - dating-apps-share-your-data -news_interviews: - - interview-de-jessica-pidoux-journal-le-temps +news: + - type: infographic + editorial: what-bumble-collects-about-you + - type: editorial + editorial: dating-apps-share-your-data + - type: interview + interview: interview-de-jessica-pidoux-journal-le-temps --- diff --git a/tools/README.md b/tools/README.md index 703c9643..fae5996f 100644 --- a/tools/README.md +++ b/tools/README.md @@ -4,4 +4,4 @@ Scripts for codebase maintenance or needed by the build & dev toolchains. `TODO` script to clone issue labels, issue milestones -and issues from the [WEBSITE.TEMPLATE](https://github.com/hestia-admin/website.template/issues/) repository, as mentioned in the step-by-step instructions of [Finishing setup of forked repository (#1)](../../issues/1). \ No newline at end of file +and issues from the [WEBSITE.TEMPLATE](https://github.com/hestiaAI/website.template/issues/) repository, as mentioned in the step-by-step instructions of [Finishing setup of forked repository (#1)](../../issues/1). \ No newline at end of file diff --git a/tools/setup-post-fork.js b/tools/setup-post-fork.js new file mode 100644 index 00000000..6e25a550 --- /dev/null +++ b/tools/setup-post-fork.js @@ -0,0 +1,253 @@ +const prompts = require('prompts'); +const replace = require('replace-in-file'); + +// const pino = require('pino'); +const path = require('path'); +const {createLogger, format, transports} = require('winston'); + +const logFile = path.join(process.cwd(),'setup-post-fork.log'); +console.log(`logs written to ${logFile}`); +const logger = createLogger({ + format: format.simple(), + transports: [new transports.File({ filename: logFile, handleExceptions: true })] +}); + +const P_SITE_TITLE = '‹SITE-TITLE›'; +const P_SITE_NAME = '‹SITE-NAME›'; +const P_SITE_SHORTNAME = '‹SITE-SHORTNAME›'; +const P_REPO_NAME = '‹REPO-NAME›'; +const P_REPO_PACKAGE_NAME = '‹REPO-PACKAGE-NAME›'; +const P_NEWSLETTER_FORM_NAME = '‹NEWSLETTER-FORM-NAME›'; +const P_CONTACT_FORM_NAME_INFO = '‹CONTACT-FORM-NAME-INFO›'; +const P_CONTACT_FORM_NAME_MEDIA = '‹CONTACT-FORM-NAME-MEDIA›'; +const P_CONTACT_FORM_NAME_PARTNERS = '‹CONTACT-FORM-NAME-PARTNERS›'; +const P_CONTACT_FORM_NAME_RESEARCHERS = '‹CONTACT-FORM-NAME-RESEARCHERS›'; +const P_SITE_URL = '‹SITE-URL›'; +const P_SITE_UUID = '‹SITE-UUID›'; +const P_SITE_OWNER_NAME = '‹SITE-OWNER-NAME›'; +const P_TWITTER_ACCOUNT_NAME = '‹TWITTER-ACCOUNT-NAME›'; +const P_FORUM_SITE_URL = '‹FORUM-SITE-URL›'; + +const SOURCE_PLACEHOLDERS = [ + P_SITE_TITLE, + P_SITE_NAME, + P_SITE_SHORTNAME, + P_REPO_NAME, + P_SITE_URL, + P_SITE_UUID, + P_SITE_OWNER_NAME, + P_TWITTER_ACCOUNT_NAME, + P_FORUM_SITE_URL]; + +const DERIVATIONS = { + [P_SITE_SHORTNAME]: [ + {name: P_REPO_PACKAGE_NAME, derive: p => `website-${p}`}, + {name: P_NEWSLETTER_FORM_NAME, derive: p => `newletter-${p}-signup`}, + {name: P_CONTACT_FORM_NAME_INFO, derive: p => `contact-${p}-info`}, + {name: P_CONTACT_FORM_NAME_MEDIA, derive: p => `contact-${p}-media`}, + {name: P_CONTACT_FORM_NAME_PARTNERS, derive: p => `contact-${p}-partners`}, + {name: P_CONTACT_FORM_NAME_RESEARCHERS, derive: p => `contact-${p}-researchers`}, + ] +}; +const allPlaceholders = (sourcePlaceholders, derivations) => + [ ...sourcePlaceholders, + ...sourcePlaceholders + .map(p => derivations[p]?.map(d => d.name)) + .filter(ds => ds) + .flat()] + +const TARGET_PATHS = ['src/**', 'conf/**', 'README.md', 'package.json']; + +const requiredValidator = + value => value.length > 0 || 'Please enter a value'; + +const urlPartValidator = value => { + if(encodeURIComponent(value) != value){ + return `The name should be valid in an url` + } + return true; +}; + +const urlValidator = value => { + // not mandatory + if(!value){return true;} + try { + new URL('http://' + value); + return true; + } catch (error) { + return "Invalid url"; + } +}; + +const composeValidators = (...validators) => (value) => + validators.reduce( + (result, validator) => result === true ? validator(value) : result, + true); + +const questions = [ + { + type: 'text', + name: P_SITE_TITLE, + message: 'Title of the website (ex: "Your Showcase")', + }, + { + type: 'text', + name: P_SITE_NAME, + message: 'Name of the website (ex: "your-showcase")', + validate: urlPartValidator + }, + { + type: 'text', + name: P_SITE_SHORTNAME, + message: 'A short name for the website (ex: "shoca")', + }, + { + type: 'text', + name: P_REPO_NAME, + message: 'Name of the github repo (ex: "website.showcase")', + }, + { + type: 'text', + name: P_SITE_URL, + message: 'URL of the website (ex: "your-showcase.hestialabs.org")', + validate: urlValidator + }, + { + type: 'text', + name: P_SITE_UUID, + message: 'Netlify Site UUID (the API ID set by netlify when the site is configured)', + }, + { + type: 'text', + name: P_SITE_OWNER_NAME, + message: 'Name of the site owner (used in package.json)', + }, + { + type: 'text', + name: P_TWITTER_ACCOUNT_NAME, + message: 'Twitter handle', + }, + { + type: 'text', + name: P_FORUM_SITE_URL, + message: 'URL of the forum', + validate: urlValidator + } + //TODO last input asks to run replacement script +]; + +const deriveValues = (vals, derivations) => + Object.entries(vals).reduce( + (allVals, [ph, val] ) => { + if (val) { + derivations[ph]?.forEach(d => { + allVals[d.name] = d.derive(val); + }) + } + return allVals; + }, + Object.assign({}, vals)); + +async function replacePlaceholders(placeholders, value, paths, dry){ + // see https://github.com/adamreisnz/replace-in-file#basic-usage + const options = { + files: paths, + from: placeholders.map(p => new RegExp(p, 'g')), + to: value, + dry + }; + if(!dry){ + const message = `replacing ${placeholders.join(' ')} with ${value}`; + console.log(message); + logger.info(message); + } + const results = await replace(options); + const files = results.filter(result => result.hasChanged) + .map(result => result.file); + if (!dry) { + files.forEach(f => { + const message = `replaced ${placeholders.join(' ')} in ${f}`; + console.log(message); + logger.info(message); + }); + } + return files; +} + +async function placeholderTodos(placeholders, derivations, path){ + const filesToProcess = await Promise.all(placeholders.map(p => { + const derived = derivations[p]?.map(d => d.name) || []; + return replacePlaceholders(derived.concat(p), '<:-D', path, true); + })); + return placeholders.reduce( + (partition, p, i) => { + const done = filesToProcess[i].length === 0; + partition[done ? 'done' : 'todo'].push(p); + return partition; + }, + { todo: [], done: [] }); +} + +const main = async () => { + const placeholders = await placeholderTodos(SOURCE_PLACEHOLDERS, DERIVATIONS, TARGET_PATHS); + if(placeholders.done.length > 0){ + logger.info(`placeholders not found in files ${placeholders.done.join(' ')}`); + console.log('The following placeholders have already been replaced:\n', + placeholders.done.join('\n')); + } + logger.info(`unreplaced placeholders ${placeholders.todo.join(' ')}`); + const unanswered = questions.filter(q => placeholders.todo.includes(q.name)); + const response = await prompts(unanswered, { + onSubmit: (prompt, answer) => { + try{ + logger.info(`user chooses ${prompt.name} = ${answer}`); + }catch(error){ + console.error(error); + logger.error(error); + } + }}); + const allValues = deriveValues(response, DERIVATIONS); + allPlaceholders(SOURCE_PLACEHOLDERS, DERIVATIONS) + .forEach(async (placeholder) => { + try{ + const value = allValues[placeholder]; + if (value) { + console.log(`${placeholder} = ${value}`); + await replacePlaceholders([placeholder], value, TARGET_PATHS, false); + } + }catch(error){ + console.error(error); + logger.error(error); + } + }); +}; + +try { + main(); +} catch (error) { + console.error(error); +} +/* + +- [x] Figure out a title for the new website ⟶ `‹SITE-TITLE›`; _`Your Showcase`_ `DONE` +- [x] Figure out a name for the new website ⟶ `‹SITE-NAME›`; _`your-showcase`_ `DONE` +- [x] Figure out a two letters short name for the new website ⟶ `‹SITE-SHORTNAME›`; _`showcase`_ `DONE` +- [x] Figure out a name for the new repository ⟶ `‹REPO-NAME›`; _`website.showcase` `DONE` + +Derived names: + +- [x] `‹REPO-PACKAGE-NAME›`⟵ `website-‹SITE-SHORTNAME›` _package name for the new repository, used in `package.json_`; same as ‹REPO-NAME›, but with dash instead of dot: `website-showcase`_ +- [x] `‹NEWSLETTER-FORM-NAME›` ⟵ `newsletter-showcase-signup` _name of the Netlify Form to which newsletter subscriptions will be submitted to_ +- [x] `‹CONTACT-FORM-NAME-INFO›` ⟵ `contact-showcase-info` +- [x] `‹CONTACT-FORM-NAME-MEDIA›` ⟵ `contact-showcase-media` +- [x] `‹CONTACT-FORM-NAME-PARTNERS›` ⟵ `contact-showcase-partners` +- [x] `‹CONTACT-FORM-NAME-RESEARCHERS›` ⟵ `contact-showcase-researchers` + +Optional at this stage, but have to be defined before site public launch: + +- [x] Decide an URL for the new website ⟶ `‹SITE-URL›` _to be reserved in Gandi and used in Netlify; for instance, `your-showcase.hestialabs.org`_ +- [ ] Get the Netlify Site UUID ⟶ `‹SITE-UUID›` _used in `README.md`_ +- [x] Decide who'll be the owner of the community ⟶ `‹SITE-OWNER-NAME›` _used in `package.json`: `Charles Foucault-Dumas`_ +- [ ] Decide a Twitter account name linked to the new website ⟶ `‹TWITTER-ACCOUNT-NAME›` +- [ ] Decide an URL for the forum linked to the new website ⟶ `‹FORUM-SITE-URL›` + */