From a80d18da5c9e3fcf5926a38dbbecd534f55374b2 Mon Sep 17 00:00:00 2001 From: Pavel Sanchez <23495830+PaleBluDot@users.noreply.github.com> Date: Mon, 20 May 2024 16:42:39 -0400 Subject: [PATCH] feat(cli): tools to make managing easy (#59) * feat(utils): create new affiliation files * chore(custom): cli ability to include comma seperated list * fix(custom): cli move to esm * chore(custom): cli add bin object * chore(cli): add cli scope add bin object * feat(cli): combine affiliations to json file add bin object * feat(cli): save local data file * feat(cli): create data loader file * fix(cli): remove minified replace function * chore(deps): add inquirer * feat(cli): update affiliation * fix(cli): run inquirer if any option is missing * feat(cli): add new signature object * chore(cli): move commands to own directory * feat(cli): parse data function * feat(cli): read file function * feat(cli): update date file function * chore(cli): sorted onject * feat(cli): alaphabetically sort object * chore(cli): moved file locations * chore(cli): ignore test command * chore(cli): update cli call command * chore(data): alphabetically sort object * chore(data): local data file --- .config/commitizen.config.js | 2 +- .gitignore | 5 +- bin/cli.mjs | 49 ++++++++ bin/commands/addNewAffiliation.mjs | 101 +++++++++++++++++ bin/commands/addNewSignature.mjs | 66 +++++++++++ bin/commands/createDataLoader.mjs | 19 ++++ bin/commands/saveLocalData.mjs | 15 +++ bin/commands/updateAffiliation.mjs | 94 ++++++++++++++++ bin/lib/combineAffiliation.mjs | 25 +++++ bin/lib/parseDataFile.mjs | 4 + bin/lib/readFile.mjs | 6 + bin/lib/sailthruVariables.mjs | 49 ++++++++ bin/lib/sortObject.mjs | 17 +++ bin/lib/updateDataFile.mjs | 38 +++++++ package-lock.json | 26 +++-- package.json | 30 +++-- src/_data/affiliations/ak.js | 50 +++++++++ src/_data/affiliations/nat.js | 65 +++++++++++ src/_data/dataLoader.json | 174 +++++++++++++++++++++-------- 19 files changed, 765 insertions(+), 70 deletions(-) create mode 100755 bin/cli.mjs create mode 100644 bin/commands/addNewAffiliation.mjs create mode 100644 bin/commands/addNewSignature.mjs create mode 100644 bin/commands/createDataLoader.mjs create mode 100644 bin/commands/saveLocalData.mjs create mode 100644 bin/commands/updateAffiliation.mjs create mode 100644 bin/lib/combineAffiliation.mjs create mode 100644 bin/lib/parseDataFile.mjs create mode 100644 bin/lib/readFile.mjs create mode 100644 bin/lib/sailthruVariables.mjs create mode 100644 bin/lib/sortObject.mjs create mode 100644 bin/lib/updateDataFile.mjs create mode 100644 src/_data/affiliations/ak.js create mode 100644 src/_data/affiliations/nat.js diff --git a/.config/commitizen.config.js b/.config/commitizen.config.js index 81ffb0f..b0508bf 100644 --- a/.config/commitizen.config.js +++ b/.config/commitizen.config.js @@ -29,7 +29,7 @@ const types = [ }, ]; -const scopes = ["components", "config", "data", "deps", "layout", "media", "partials", "styles", "templates", "test", "utils"].map((name) => ({ +const scopes = ["components", "config", "cli", "data", "deps", "layout", "media", "partials", "styles", "templates", "test", "utils"].map((name) => ({ name, })); diff --git a/.gitignore b/.gitignore index 5138465..1dfdb49 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ # dependencies node_modules/ + +# test files .vscode/settings.json -src/_data/affiliations/xx.js +src/**/**/xx.js src/test/xx.test.js +bin/commands/testCommand.mjs # build artifacts build/ diff --git a/bin/cli.mjs b/bin/cli.mjs new file mode 100755 index 0000000..cf9de2c --- /dev/null +++ b/bin/cli.mjs @@ -0,0 +1,49 @@ +#!/usr/bin/env node + +import { program } from "commander"; +import addNewAffiliation from "./commands/addNewAffiliation.mjs"; +import addNewSignature from "./commands/addNewSignature.mjs"; +import saveLocalData from "./commands/saveLocalData.mjs"; +import createDataLoader from "./commands/createDataLoader.mjs"; +import updateAffiliation from "./commands/updateAffiliation.mjs"; + +program + .command("add [name]") + .description("Add a new affiliation") + .action((name) => addNewAffiliation(name)); + +program + .command("signature [name]") + .description("Create new signature object") + .action((name) => addNewSignature(name)); + +program + .command("save [name]") + .description("Create local json data file") + .option("-l, --location ", "location to save the file") + .action((name, cmdObj) => { + const location = cmdObj.location; + saveLocalData(name, location); + }); + +program + .command("create [location]") + .description("Create Sailthru data loader file") + .action((location) => createDataLoader(location)); + +program + .command("update [options...]") + .description("Update the value for a key") + .option("-a, --affiliation ", "affiliation name") + .option("-k, --key ", "key to replace") + .option("-v, --value ", "new value") + .action((optionsArgs, cmdObj) => { + const options = { + affiliation: cmdObj.affiliation, + key: cmdObj.key, + value: cmdObj.value, + }; + updateAffiliation(options); + }); + +program.parse(process.argv); diff --git a/bin/commands/addNewAffiliation.mjs b/bin/commands/addNewAffiliation.mjs new file mode 100644 index 0000000..791726b --- /dev/null +++ b/bin/commands/addNewAffiliation.mjs @@ -0,0 +1,101 @@ +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +function addNewAffiliation(names) { + if (!names) { + console.error("Names are required"); + return; + } + + const dirPath = path.join(__dirname, "../../src/_data/affiliations"); + + if (!fs.existsSync(dirPath)) { + fs.mkdirSync(dirPath, { recursive: true }); + } + + const namesArray = names.includes(",") ? names.split(",") : [names]; + + namesArray.forEach((name) => { + const filePath = path.join(dirPath, `${name}.js`); + + const template = `const data = { + address1: "", + address2: "", + affiliation_name: "", + donation_url: "", + facebook_url: "", + instagram_url: "", + logo_url: "", + logo_width: "150", + signatures: { + advo: { + title: "Chief Political and Advocacy Officer", + name: "", + pronouns: "", + headshot: "", + }, + comms: { + title: "Chief Communications and Marketing Officer", + name: "", + pronouns: "", + headshot: "", + }, + custom1: { + title: "", + name: "", + pronouns: "", + headshot: "", + }, + custom2: { + title: "", + name: "", + pronouns: "", + headshot: "", + }, + custom3: { + title: "", + name: "", + pronouns: "", + headshot: "", + }, + dev: { + title: "Chief Development Officer", + name: "", + pronouns: "", + headshot: "", + }, + ed: { + title: "Executive Director", + name: "", + pronouns: "", + headshot: "", + }, + legal: { + title: "Legal Director", + name: "", + pronouns: "", + headshot: "", + }, + }, + twitter_url: "", + website_url: "", +}; + +module.exports = data; +`; + + fs.writeFile(filePath, template, (err) => { + if (err) { + console.error(`Error creating file: ${err}`); + } else { + console.log(`Created new affiliation file at ${filePath}`); + } + }); + }); +} + +export default addNewAffiliation; diff --git a/bin/commands/addNewSignature.mjs b/bin/commands/addNewSignature.mjs new file mode 100644 index 0000000..ea0bc1b --- /dev/null +++ b/bin/commands/addNewSignature.mjs @@ -0,0 +1,66 @@ +import fs from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; +import { createRequire } from "module"; +import sortObject from "../lib/sortObject.mjs"; + +const require = createRequire(import.meta.url); + +function toJS(object) { + return `const data = ${sortObject(object)};\n\nmodule.exports = data;`; +} + +function createSailthruSigVariable(sig) { + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const filePath = path.join(__dirname, "../lib/sailthruVariables.mjs"); + + let sailthruVariables = fs.readFileSync(filePath, "utf8"); + + const sailthruSignatureVariables = ` +{${sig}_name = data[affiliation]['signatures']['${sig}']['name']} +{${sig}_title = data[affiliation]['signatures']['${sig}']['title']} +{${sig}_pronouns = data[affiliation]['signatures']['${sig}']['pronouns']} +{${sig}_headshot = data[affiliation]['signatures']['${sig}']['headshot']} +`; + + sailthruVariables = sailthruVariables.replace("`;\n\nexport default sailthruVariables;", sailthruSignatureVariables + "`;\n\nexport default sailthruVariables;"); + + fs.writeFileSync(filePath, sailthruVariables); +} + +export default function addNewSignature(name) { + if (!name) { + console.error("Name is required"); + return; + } + + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const directory = path.join(__dirname, "../../src/_data/affiliations"); + const files = fs.readdirSync(directory); + + createSailthruSigVariable(name); + + for (const file of files) { + const filePath = path.join(directory, file); + let data; + try { + data = require(filePath); + } catch (err) { + console.error("Failed to import module", err); + continue; + } + + if (!data.signatures) { + data.signatures = {}; + } + + data.signatures[name] = { + title: "", + name: "", + pronouns: "", + headshot: "", + }; + + fs.writeFileSync(filePath, toJS(data)); + } +} diff --git a/bin/commands/createDataLoader.mjs b/bin/commands/createDataLoader.mjs new file mode 100644 index 0000000..4a3c734 --- /dev/null +++ b/bin/commands/createDataLoader.mjs @@ -0,0 +1,19 @@ +import fs from "fs"; +import path from "path"; +import getCombinedData from "../lib/combineAffiliation.mjs"; +import sailthruVariables from "../lib/sailthruVariables.mjs"; + +export default function createLoaderFile(location = "build/data") { + getCombinedData().then((data) => { + const minifiedJson = "{data = " + JSON.stringify(data) + "}"; + const distPath = path.join(location, "dataLoader.min.json"); + let combineData = minifiedJson + sailthruVariables; + + fs.mkdirSync(location, { recursive: true }); + + fs.writeFile(distPath, combineData, (err) => { + if (err) throw err; + console.log("HTML Content data written to:", distPath); + }); + }); +} diff --git a/bin/commands/saveLocalData.mjs b/bin/commands/saveLocalData.mjs new file mode 100644 index 0000000..8e4e58f --- /dev/null +++ b/bin/commands/saveLocalData.mjs @@ -0,0 +1,15 @@ +import fs from "fs"; +import path from "path"; +import getCombinedData from "../lib/combineAffiliation.mjs"; + +export default function saveCombinedData(name = "dataLoader", location = "src/_data") { + getCombinedData().then((data) => { + const savePath = path.join(location, `${name}.json`); + const jsonData = JSON.stringify(data, null, 2); + + fs.mkdirSync(location, { recursive: true }); + + fs.writeFileSync(savePath, jsonData); + console.log("Data saved to", savePath); + }); +} diff --git a/bin/commands/updateAffiliation.mjs b/bin/commands/updateAffiliation.mjs new file mode 100644 index 0000000..4a5a278 --- /dev/null +++ b/bin/commands/updateAffiliation.mjs @@ -0,0 +1,94 @@ +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; +import inquirer from "inquirer"; +import util from "util"; +import updateDataFile from "../lib/updateDataFile.mjs"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const affiliationsDir = path.join(__dirname, "../../src/_data/affiliations"); + +export default function updateAffiliation(options = {}) { + const files = fs.readdirSync(affiliationsDir); + const affiliations = files.map((file) => path.basename(file, ".js")); + + inquirer + .prompt([ + { + type: "list", + name: "affiliation", + message: "Select the affiliation to update:", + choices: affiliations, + default: options.affiliation, + when: () => !options.affiliation, + }, + ]) + .then((answers) => { + const affiliation = options.affiliation || answers.affiliation; + const filePath = path.join(affiliationsDir, `${affiliation}.js`); + + import(filePath).then((content) => { + const keys = Object.keys(content.default); + + inquirer + .prompt([ + { + type: "list", + name: "key", + message: "Select the key to replace:", + choices: keys, + default: options.key, + when: () => !options.key, + }, + { + type: "input", + name: "value", + message: "Enter the new value:", + default: options.value, + when: (answers2) => !options.value && answers2.key !== "signatures", + }, + ]) + .then((answers2) => { + const key = options.key || answers2.key; + const value = options.value || answers2.value; + + if (key === "signatures") { + const signatureKeys = Object.keys(content.default.signatures); + + inquirer + .prompt([ + { + type: "list", + name: "signatureKey", + message: "Select the signature to replace:", + choices: signatureKeys, + }, + ]) + .then((answers3) => { + const signatureProperties = Object.keys(content.default.signatures[answers3.signatureKey]); + + inquirer + .prompt([ + { + type: "list", + name: "signatureProperty", + message: "Select the property to replace:", + choices: signatureProperties, + }, + { + type: "input", + name: "value", + message: "Enter the new value:", + }, + ]) + .then((answers4) => { + updateDataFile(affiliation, `signatures.${answers3.signatureKey}.${answers4.signatureProperty}`, answers4.value); + }); + }); + } else { + updateDataFile(affiliation, key, value); + } + }); + }); + }); +} diff --git a/bin/lib/combineAffiliation.mjs b/bin/lib/combineAffiliation.mjs new file mode 100644 index 0000000..236bf32 --- /dev/null +++ b/bin/lib/combineAffiliation.mjs @@ -0,0 +1,25 @@ +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const affiliationsDir = path.join(__dirname, "../../src/_data/affiliations"); +const files = fs.readdirSync(affiliationsDir); + +function getCombinedData() { + let combinedData = {}; + + const imports = files.map((file) => { + const filePath = path.join(affiliationsDir, file); + return import(filePath).then((data) => { + const affiliation = path.basename(file, path.extname(file)); + combinedData[affiliation] = data.default; + }); + }); + + return Promise.all(imports).then(() => combinedData); +} + +export default getCombinedData; diff --git a/bin/lib/parseDataFile.mjs b/bin/lib/parseDataFile.mjs new file mode 100644 index 0000000..38d6f2a --- /dev/null +++ b/bin/lib/parseDataFile.mjs @@ -0,0 +1,4 @@ +export default async function parseDataFile(data) { + const module = await import(data); + return module.default; +} diff --git a/bin/lib/readFile.mjs b/bin/lib/readFile.mjs new file mode 100644 index 0000000..51e50b1 --- /dev/null +++ b/bin/lib/readFile.mjs @@ -0,0 +1,6 @@ +import fs from "fs"; + +export default function readFile(path) { + const data = fs.readFileSync(path, "utf8"); + return data; +} diff --git a/bin/lib/sailthruVariables.mjs b/bin/lib/sailthruVariables.mjs new file mode 100644 index 0000000..61248d4 --- /dev/null +++ b/bin/lib/sailthruVariables.mjs @@ -0,0 +1,49 @@ +const sailthruVariables = ` +{affiliation = lower(split(blast.name, ' ')[1])} +{affiliation_name = data[affiliation]["affiliation_name"]} +{address1 = data[affiliation]["address1"]} +{address2 = data[affiliation]["address2"]} +{donation_url = data[affiliation]["donation_url"]} +{facebook_url = data[affiliation]["facebook_url"]} +{instagram_url = data[affiliation]["instagram_url"]} +{logo_url = data[affiliation]["logo_url"]} +{logo_width = data[affiliation]["logo_width"]} +{twitter_url = data[affiliation]["twitter_url"]} +{website_url = data[affiliation]["website_url"]} +{email_pref = "https://action.aclu.org/preference-center/aclu-" + affiliation + "-email-preference?eid=" + email_id + "&referral=" + affiliation + "&unsub_url=" + optout_confirm_url} +{facebook_logo = "https://media.sailthru.com/64d/1k3/a/o/5db1cb21b75bf.png"} +{instagram_logo = "https://media.sailthru.com/64d/1k3/a/o/5db1cb1be2cb6.png"} +{twitter_logo = "https://media.sailthru.com/64d/1k3/a/o/5db1cb153c9f8.png"} +{privacy_statement = "https://www.aclu.org/american-civil-liberties-union-privacy-statement"} + +{advo_name = data[affiliation]['signatures']['advo']['name']} +{advo_title = data[affiliation]['signatures']['advo']['title']} +{advo_pronouns = data[affiliation]['signatures']['advo']['pronouns']} +{advo_headshot = data[affiliation]['signatures']['advo']['headshot']} + +{comms_name = data[affiliation]['signatures']['comms']['name']} +{comms_title = data[affiliation]['signatures']['comms']['title']} +{comms_pronouns = data[affiliation]['signatures']['comms']['pronouns']} +{comms_headshot = data[affiliation]['signatures']['comms']['headshot']} + +{comms_name = data[affiliation]['signatures']['comms']['name']} +{comms_title = data[affiliation]['signatures']['comms']['title']} +{comms_pronouns = data[affiliation]['signatures']['comms']['pronouns']} +{comms_headshot = data[affiliation]['signatures']['comms']['headshot']} + +{dev_name = data[affiliation]['signatures']['dev']['name']} +{dev_title = data[affiliation]['signatures']['dev']['title']} +{dev_pronouns = data[affiliation]['signatures']['dev']['pronouns']} +{dev_headshot = data[affiliation]['signatures']['dev']['headshot']} + +{ed_name = data[affiliation]['signatures']['ed']['name']} +{ed_title = data[affiliation]['signatures']['ed']['title']} +{ed_pronouns = data[affiliation]['signatures']['ed']['pronouns']} +{ed_headshot = data[affiliation]['signatures']['ed']['headshot']} +{legal_name = data[affiliation]['signatures']['legal']['name']} +{legal_title = data[affiliation]['signatures']['legal']['title']} +{legal_pronouns = data[affiliation]['signatures']['legal']['pronouns']} +{legal_headshot = data[affiliation]['signatures']['legal']['headshot']} +`; + +export default sailthruVariables; diff --git a/bin/lib/sortObject.mjs b/bin/lib/sortObject.mjs new file mode 100644 index 0000000..3951f11 --- /dev/null +++ b/bin/lib/sortObject.mjs @@ -0,0 +1,17 @@ +export default function stringifyObject(obj, indent = " ") { + const isArray = Array.isArray(obj); + const entries = Object.entries(obj) + .sort(([keyA], [keyB]) => keyA.localeCompare(keyB)) + .map(([key, value]) => { + key = isArray ? "" : key + ": "; + if (value && typeof value === "object") { + value = stringifyObject(value, indent + " "); + } else if (typeof value === "string") { + value = `'${value}'`; + } + return indent + key + value; + }); + const start = isArray ? "[" : "{"; + const end = isArray ? "]" : "}"; + return `${start}\n${entries.join(",\n")}\n${indent.slice(2)}${end}`; +} diff --git a/bin/lib/updateDataFile.mjs b/bin/lib/updateDataFile.mjs new file mode 100644 index 0000000..41d967f --- /dev/null +++ b/bin/lib/updateDataFile.mjs @@ -0,0 +1,38 @@ +// update.js +import fs from "fs"; +import path, { dirname } from "path"; +import { fileURLToPath } from "url"; +import util from "util"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const affiliationsDir = path.join(__dirname, "../../src/_data/affiliations"); + +export default function updateFile(affiliation, key, value) { + const filePath = path.join(affiliationsDir, `${affiliation}.js`); + + import(filePath).then((content) => { + const keys = key.split("."); + let target = content.default; + + for (let i = 0; i < keys.length - 1; i++) { + if (keys[i] === "signatures") { + target = target[keys[i]][keys[i + 1]]; + i++; + } else { + target = target[keys[i]]; + } + } + + target[keys[keys.length - 1]] = value; + + const output = `const data = ${util.inspect(content.default, { depth: null })};\n\nmodule.exports = data;`; + + fs.writeFile(filePath, output, (err) => { + if (err) { + console.error(`Error writing file: ${err}`); + } else { + console.log(`\nUpdated affiliation file at ${filePath}`); + } + }); + }); +} diff --git a/package-lock.json b/package-lock.json index 53b3729..fec8fd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,11 @@ "name": "@aclu-national/email-builder", "version": "1.8.1", "license": "MIT", + "bin": { + "aclu-email-script": "bin/cli.mjs", + "aes": "bin/cli.mjs", + "email-builder": "bin/cli.mjs" + }, "devDependencies": { "@11ty/eleventy": "^2.0.1", "@semantic-release/changelog": "^6.0.3", @@ -21,13 +26,16 @@ "cspell": "^5.10.1", "cz-customizable": "^6.3.0", "husky": "^7.0.1", - "inquirer": "^9.2.15", + "inquirer": "^9.2.16", "jest": "^29.7.0", "lint-staged": "^10.2.11", "npm-run-all": "^4.1.5", "pa11y": "^5.3.0", "prettier": "^2.4.1", "semantic-release": "^21.1.1" + }, + "engines": { + "node": ">=18" } }, "node_modules/@11ty/dependency-tree": { @@ -1901,12 +1909,12 @@ } }, "node_modules/@ljharb/through": { - "version": "2.3.12", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.12.tgz", - "integrity": "sha512-ajo/heTlG3QgC8EGP6APIejksVAYt4ayz4tqoP3MolFELzcH1x1fzwEYRJTPO0IELutZ5HQ0c26/GqAYy79u3g==", + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", + "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.5" + "call-bind": "^1.0.7" }, "engines": { "node": ">= 0.4" @@ -7447,12 +7455,12 @@ "dev": true }, "node_modules/inquirer": { - "version": "9.2.15", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", - "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", + "version": "9.2.16", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.16.tgz", + "integrity": "sha512-qzgbB+yNjgSzk2omeqMDtO9IgJet/UL67luT1MaaggRpGK73DBQct5Q4pipwFQcIKK1GbMODYd4UfsRCkSP1DA==", "dev": true, "dependencies": { - "@ljharb/through": "^2.3.12", + "@ljharb/through": "^2.3.13", "ansi-escapes": "^4.3.2", "chalk": "^5.3.0", "cli-cursor": "^3.1.0", diff --git a/package.json b/package.json index 349052d..2d4a6a9 100644 --- a/package.json +++ b/package.json @@ -1,30 +1,38 @@ { "name": "@aclu-national/email-builder", "version": "1.8.1", - "description": "Using 11ty to generate HTML emails", + "description": "Using 11ty to generate ACLU HTML email templates.", "main": "dist/", "author": "ACLU", + "license": "MIT", + "private": true, "contributors": [ "Pavel Sanchez", "Brennan Taylor", "Stephen Demo", "Ashley Burrous" ], - "license": "MIT", - "private": true, + "keywords": [ + "eleventy", + "HTML", + "email" + ], + "bin": { + "email-builder": "./bin/cli.mjs", + "aclu-email-builder": "./bin/cli.mjs", + "aeb": "./bin/cli.mjs" + }, "scripts": { - "start": "npm-run-all clean --parallel dev format", + "start": "npm run dev", "dev": "eleventy --serve", "web": "eleventy", "clean": "rimraf dist/", "pa11y": "pa11y ./dist", - "spellcheck": "npx cspell dist/**", "lint": "npm run pa11y", "format": "npx prettier --write dist/**/*", "commit": "git cz", "test": "jest --verbose", "qa": "npm-run-all clean --parallel lint test", - "cli": "node --no-warnings src/utils/cli.js", "build": "npm run clean && cross-env ELEVENTY_ENV=prod eleventy" }, "config": { @@ -44,11 +52,9 @@ "lint-staged": { "*.{html,md,json,js}": "npm run format" }, - "keywords": [ - "eleventy", - "HTML", - "email" - ], + "engines": { + "node": ">=18" + }, "devDependencies": { "@11ty/eleventy": "^2.0.1", "@semantic-release/changelog": "^6.0.3", @@ -62,7 +68,7 @@ "cspell": "^5.10.1", "cz-customizable": "^6.3.0", "husky": "^7.0.1", - "inquirer": "^9.2.15", + "inquirer": "^9.2.16", "jest": "^29.7.0", "lint-staged": "^10.2.11", "npm-run-all": "^4.1.5", diff --git a/src/_data/affiliations/ak.js b/src/_data/affiliations/ak.js new file mode 100644 index 0000000..5d38fc0 --- /dev/null +++ b/src/_data/affiliations/ak.js @@ -0,0 +1,50 @@ +const data = { + address1: "1057 W. Fireweed Lane, Suite 207", + address2: "Anchorage, AK 99052", + affiliation_name: "ACLU of Alaska", + donation_url: "https://action.aclu.org/give/alaska-join-renew-today?initms_aff=ak&initms_chan=eml&utm_medium=eml&initms=22XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=22XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=ak&ms_chan=eml&ms=22XXXX_affcampaign_footerdonate_gradead_sail", + facebook_url: "https://www.facebook.com/ACLUofAlaska", + instagram_url: "https://www.instagram.com/acluofalaska", + logo_url: "https://media.sailthru.com/64d/1k4/4/d/5e947c159341b.png", + logo_width: "150", + privacy_url: "https://www.acluak.org/en/privacy-statement", + signatures: { + advo: { + headshot: "", + name: "Michael Garvey", + pronouns: "", + title: "Advocacy Director", + }, + comms: { + headshot: "https://media.sailthru.com/64d/1k4/4/s/5ea873c8f3d44.jpg", + name: "Megan Edge", + pronouns: "She, her, hers", + title: "Communications Director", + }, + custom1: { headshot: "", name: "", pronouns: "", title: "" }, + custom2: { headshot: "", name: "Pavel Sanchez", pronouns: "", title: "" }, + custom3: { headshot: "", name: "", pronouns: "", title: "" }, + dev: { + headshot: "https://media.sailthru.com/64d/1k4/4/s/5ea873c4a1b08.jpg", + name: "Laura Herman", + pronouns: "She, her, hers", + title: "Director of Philanthropy", + }, + ed: { + headshot: "https://media.sailthru.com/64d/1k4/3/2/5e5d757771747.jpg", + name: "Joshua Decker", + pronouns: "He, him, his", + title: "Executive Director", + }, + legal: { + headshot: "https://media.sailthru.com/64d/1k4/4/s/5ea873be7af4e.jpg", + name: "Stephen Koteff", + pronouns: "", + title: "Legal Director", + }, + }, + twitter_url: "https://twitter.com/ACLUofAlaska", + website_url: "https://www.acluak.org", +}; + +module.exports = data; diff --git a/src/_data/affiliations/nat.js b/src/_data/affiliations/nat.js new file mode 100644 index 0000000..ca31bb7 --- /dev/null +++ b/src/_data/affiliations/nat.js @@ -0,0 +1,65 @@ +const data = { + address1: "125 Broad St.", + address2: "New York, NY 10004", + affiliation_name: "ACLU", + donation_url: "https://action.aclu.org/give/protect-rights-freedoms-we-believe-4-multistep?initms_aff=nat&initms_chan=eml&utm_medium=eml&initms=21XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=21XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=nat&ms_chan=eml&ms=21XXXX_affcampaign_footerdonate_gradead_sail", + facebook_url: "https://www.facebook.com/aclu", + instagram_url: "https://www.instagram.com/aclu_nationwide/", + logo_url: "https://media.sailthru.com/64d/1k3/a/o/5db1cbcdd662a.png", + logo_width: "150", + privacy_url: "https://www.aclu.org/about/privacy/statement", + signatures: { + advo: { + headshot: "", + name: "Deirdre Schifeling", + pronouns: "She, her, hers", + title: "Chief Political and Advocacy Officer", + }, + comms: { + headshot: "", + name: "Kriston Alford McIntosh", + pronouns: "She, her, hers", + title: "Chief Communications and Marketing Officer", + }, + custom1: { + headshot: "", + name: "Liz FitzGerald", + pronouns: "She, her, hers", + title: "Director of Development", + }, + custom2: { + headshot: "", + name: "Sarah Bleviss", + pronouns: "She, her, hers", + title: "Director, Digital Campaigns", + }, + custom3: { + headshot: "", + name: "Pavel Sanchez", + pronouns: "He, him, his", + title: "Associate Director, Affiliate Digital Campaigns", + }, + dev: { + headshot: "", + name: "Mark Wier", + pronouns: "He, him, his", + title: "Chief Development Officer", + }, + ed: { + headshot: "https://media.sailthru.com/64d/1k3/a/o/5db2043ae79b8.jpg", + name: "Anthony Romero", + pronouns: "He, him, his", + title: "Executive Director", + }, + legal: { + headshot: "https://media.sailthru.com/64d/1k3/a/o/5db2048b5dfce.jpg", + name: "David Cole", + pronouns: "", + title: "Legal Director", + }, + }, + twitter_url: "https://twitter.com/aclu", + website_url: "https://www.aclu.org/", +}; + +module.exports = data; diff --git a/src/_data/dataLoader.json b/src/_data/dataLoader.json index dc604c3..f0a926e 100644 --- a/src/_data/dataLoader.json +++ b/src/_data/dataLoader.json @@ -1,48 +1,128 @@ { - "ak": { - "address1": "1057 W. Fireweed Lane, Suite 207", - "address2": "Anchorage, AK 99052", - "affiliation_name": "ACLU of Alaska", - "donation_url": "https://action.aclu.org/give/alaska-join-renew-today?initms_aff=ak&initms_chan=eml&utm_medium=eml&initms=22XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=22XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=ak&ms_chan=eml&ms=22XXXX_affcampaign_footerdonate_gradead_sail", - "facebook_url": "https://www.facebook.com/ACLUofAlaska", - "instagram_url": "https://www.instagram.com/acluofalaska", - "logo_url": "https://media.sailthru.com/64d/1k4/4/d/5e947c159341b.png", - "logo_width": "150", - "privacy_url": "https://www.acluak.org/en/privacy-statement", - "twitter_url": "https://twitter.com/ACLUofAlaska", - "website_url": "https://www.acluak.org", - "signatures": { - "ed": { "title": "Executive Director", "name": "Joshua Decker", "pronouns": "He, him, his", "headshot": "https://media.sailthru.com/64d/1k4/3/2/5e5d757771747.jpg" }, - "advo": { "title": "Advocacy Director", "name": "Michael Garvey", "pronouns": "", "headshot": "" }, - "comms": { "title": "Communications Director", "name": "Megan Edge", "pronouns": "She, her, hers", "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873c8f3d44.jpg" }, - "dev": { "title": "Director of Philanthropy", "name": "Laura Herman", "pronouns": "She, her, hers", "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873c4a1b08.jpg" }, - "legal": { "title": "Legal Director", "name": "Stephen Koteff", "pronouns": "", "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873be7af4e.jpg" }, - "custom1": { "title": "", "name": "", "pronouns": "", "headshot": "" }, - "custom2": { "title": "", "name": "", "pronouns": "", "headshot": "" }, - "custom3": { "title": "", "name": "", "pronouns": "", "headshot": "" } - } - }, - "nat": { - "address1": "125 Broad St.", - "address2": "New York, NY 10004", - "affiliation_name": "ACLU", - "donation_url": "https://action.aclu.org/give/protect-rights-freedoms-we-believe-4-multistep?initms_aff=nat&initms_chan=eml&utm_medium=eml&initms=21XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=21XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=nat&ms_chan=eml&ms=21XXXX_affcampaign_footerdonate_gradead_sail", - "facebook_url": "https://www.facebook.com/aclu", - "instagram_url": "https://www.instagram.com/aclu_nationwide/", - "logo_url": "https://media.sailthru.com/64d/1k3/a/o/5db1cbcdd662a.png", - "logo_width": "150", - "privacy_url": "https://www.aclu.org/about/privacy/statement", - "twitter_url": "https://twitter.com/aclu", - "website_url": "https://www.aclu.org/", - "signatures": { - "ed": { "title": "Executive Director", "name": "Anthony Romero", "pronouns": "He, him, his", "headshot": "https://media.sailthru.com/64d/1k3/a/o/5db2043ae79b8.jpg" }, - "advo": { "title": "Chief Political and Advocacy Officer", "name": "Deirdre Schifeling", "pronouns": "She, her, hers", "headshot": "" }, - "comms": { "title": "Chief Communications and Marketing Officer", "name": "Kriston Alford McIntosh", "pronouns": "She, her, hers", "headshot": "" }, - "dev": { "title": "Chief Development Officer", "name": "Mark Wier", "pronouns": "He, him, his", "headshot": "" }, - "legal": { "title": "Legal Director", "name": "David Cole", "pronouns": "", "headshot": "https://media.sailthru.com/64d/1k3/a/o/5db2048b5dfce.jpg" }, - "custom1": { "title": "Director of Development", "name": "Liz FitzGerald", "pronouns": "She, her, hers", "headshot": "" }, - "custom2": { "title": "Director, Digital Campaigns", "name": "Sarah Bleviss", "pronouns": "She, her, hers", "headshot": "" }, - "custom3": { "title": "Associate Director, Affiliate Digital Campaigns", "name": "Pavel Sanchez", "pronouns": "He, him, his", "headshot": "" } - } - } -} + "ak": { + "address1": "1057 W. Fireweed Lane, Suite 207", + "address2": "Anchorage, AK 99052", + "affiliation_name": "ACLU of Alaska", + "donation_url": "https://action.aclu.org/give/alaska-join-renew-today?initms_aff=ak&initms_chan=eml&utm_medium=eml&initms=22XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=22XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=ak&ms_chan=eml&ms=22XXXX_affcampaign_footerdonate_gradead_sail", + "facebook_url": "https://www.facebook.com/ACLUofAlaska", + "instagram_url": "https://www.instagram.com/acluofalaska", + "logo_url": "https://media.sailthru.com/64d/1k4/4/d/5e947c159341b.png", + "logo_width": "150", + "privacy_url": "https://www.acluak.org/en/privacy-statement", + "signatures": { + "advo": { + "headshot": "", + "name": "Michael Garvey", + "pronouns": "", + "title": "Advocacy Director" + }, + "comms": { + "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873c8f3d44.jpg", + "name": "Megan Edge", + "pronouns": "She, her, hers", + "title": "Communications Director" + }, + "custom1": { + "headshot": "", + "name": "", + "pronouns": "", + "title": "" + }, + "custom2": { + "headshot": "", + "name": "Pavel Sanchez", + "pronouns": "", + "title": "" + }, + "custom3": { + "headshot": "", + "name": "", + "pronouns": "", + "title": "" + }, + "dev": { + "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873c4a1b08.jpg", + "name": "Laura Herman", + "pronouns": "She, her, hers", + "title": "Director of Philanthropy" + }, + "ed": { + "headshot": "https://media.sailthru.com/64d/1k4/3/2/5e5d757771747.jpg", + "name": "Joshua Decker", + "pronouns": "He, him, his", + "title": "Executive Director" + }, + "legal": { + "headshot": "https://media.sailthru.com/64d/1k4/4/s/5ea873be7af4e.jpg", + "name": "Stephen Koteff", + "pronouns": "", + "title": "Legal Director" + } + }, + "twitter_url": "https://twitter.com/ACLUofAlaska", + "website_url": "https://www.acluak.org" + }, + "nat": { + "address1": "125 Broad St.", + "address2": "New York, NY 10004", + "affiliation_name": "ACLU", + "donation_url": "https://action.aclu.org/give/protect-rights-freedoms-we-believe-4-multistep?initms_aff=nat&initms_chan=eml&utm_medium=eml&initms=21XXXX_affcampaign_footerdonate_gradead_sail&utm_source=sail&utm_campaign=affcampaign&utm_content=21XXXX_civilliberties_footerdonate_gradead&af={sb_query_string_encrypted}&ms_aff=nat&ms_chan=eml&ms=21XXXX_affcampaign_footerdonate_gradead_sail", + "facebook_url": "https://www.facebook.com/aclu", + "instagram_url": "https://www.instagram.com/aclu_nationwide/", + "logo_url": "https://media.sailthru.com/64d/1k3/a/o/5db1cbcdd662a.png", + "logo_width": "150", + "privacy_url": "https://www.aclu.org/about/privacy/statement", + "signatures": { + "advo": { + "headshot": "", + "name": "Deirdre Schifeling", + "pronouns": "She, her, hers", + "title": "Chief Political and Advocacy Officer" + }, + "comms": { + "headshot": "", + "name": "Kriston Alford McIntosh", + "pronouns": "She, her, hers", + "title": "Chief Communications and Marketing Officer" + }, + "custom1": { + "headshot": "", + "name": "Liz FitzGerald", + "pronouns": "She, her, hers", + "title": "Director of Development" + }, + "custom2": { + "headshot": "", + "name": "Sarah Bleviss", + "pronouns": "She, her, hers", + "title": "Director, Digital Campaigns" + }, + "custom3": { + "headshot": "", + "name": "Pavel Sanchez", + "pronouns": "He, him, his", + "title": "Associate Director, Affiliate Digital Campaigns" + }, + "dev": { + "headshot": "", + "name": "Mark Wier", + "pronouns": "He, him, his", + "title": "Chief Development Officer" + }, + "ed": { + "headshot": "https://media.sailthru.com/64d/1k3/a/o/5db2043ae79b8.jpg", + "name": "Anthony Romero", + "pronouns": "He, him, his", + "title": "Executive Director" + }, + "legal": { + "headshot": "https://media.sailthru.com/64d/1k3/a/o/5db2048b5dfce.jpg", + "name": "David Cole", + "pronouns": "", + "title": "Legal Director" + } + }, + "twitter_url": "https://twitter.com/aclu", + "website_url": "https://www.aclu.org/" + } +} \ No newline at end of file