diff --git a/.gitignore b/.gitignore index 76d7e3e9186..3dbc88d0866 100644 --- a/.gitignore +++ b/.gitignore @@ -77,6 +77,7 @@ sites/strapi/.cache # Sites prebuild artifacts sites/*/public/locales/*/*.json sites/*/public/feeds/* +packages/new-design/shared/public/locales/*/*.json # Lab auto-generated pages sites/lab/lib diff --git a/config/software/packages.json b/config/software/packages.json index ef958c22502..546a6c48098 100644 --- a/config/software/packages.json +++ b/config/software/packages.json @@ -8,6 +8,7 @@ "i18n": "Translations for the FreeSewing project", "models": "Body measurements data for a range of default sizes", "mui-theme": "A Material-UI theme for FreeSewing web UIs", + "new-design": "Initializer package for a new FreeSewing design: npx @freesewing/new-design", "pattern-info": "Information about available freesewing patterns", "prettier-config": "FreeSewing's shared configuration for prettier", "remark-jargon": "A Remark plugin for jargon terms", diff --git a/packages/i18n/src/locales/en/components/common.yaml b/packages/i18n/src/locales/en/components/common.yaml index 51a7b891738..9a875c4143c 100644 --- a/packages/i18n/src/locales/en/components/common.yaml +++ b/packages/i18n/src/locales/en/components/common.yaml @@ -9,3 +9,5 @@ requiredMeasurements: Required measurements showcase: Showcase sloganCome: Come for the sewing patterns sloganStay: Stay for the community +support: Support + diff --git a/packages/i18n/src/locales/en/components/patrons.yaml b/packages/i18n/src/locales/en/components/patrons.yaml index f2b47874c01..a92f87d638b 100644 --- a/packages/i18n/src/locales/en/components/patrons.yaml +++ b/packages/i18n/src/locales/en/components/patrons.yaml @@ -1,2 +1,5 @@ becomeAPatron: Become a patron supportFreesewing: Support FreeSewing +patronLead: FreeSewing is fuelled by a voluntary subscription model +patronPitch: If you think what we do is worthwhile, and if you can spare a few coins each month without hardship, please support our work + diff --git a/packages/i18n/src/next/en/common.mjs b/packages/i18n/src/next/en/common.mjs index 2b11a7858cc..1ed218daaf8 100644 --- a/packages/i18n/src/next/en/common.mjs +++ b/packages/i18n/src/next/en/common.mjs @@ -13,7 +13,8 @@ const common = { "requiredMeasurements": "Required measurements", "showcase": "Showcase", "sloganCome": "Come for the sewing patterns", - "sloganStay": "Stay for the community" + "sloganStay": "Stay for the community", + "support": "Support" } export default common diff --git a/packages/i18n/src/next/en/patrons.mjs b/packages/i18n/src/next/en/patrons.mjs index 3f9e4ed30a1..ebe13e2b382 100644 --- a/packages/i18n/src/next/en/patrons.mjs +++ b/packages/i18n/src/next/en/patrons.mjs @@ -4,7 +4,9 @@ */ const patrons = { "becomeAPatron": "Become a patron", - "supportFreesewing": "Support FreeSewing" + "supportFreesewing": "Support FreeSewing", + "patronLead": "FreeSewing is fuelled by a voluntary subscription model", + "patronPitch": "If you think what we do is worthwhile, and if you can spare a few coins each month without hardship, please support our work" } export default patrons diff --git a/packages/new-design/CHANGELOG.md b/packages/new-design/CHANGELOG.md new file mode 100644 index 00000000000..7274b9130ec --- /dev/null +++ b/packages/new-design/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change log for: @freesewing/new-design + + + +This is the **initial release**, and the start of this change log. + +> Prior to version 2, FreeSewing was not a JavaScript project. +> As such, that history is out of scope for this change log. + diff --git a/packages/new-design/README.md b/packages/new-design/README.md new file mode 100644 index 00000000000..cd7325f2d84 --- /dev/null +++ b/packages/new-design/README.md @@ -0,0 +1,260 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

@freesewing/new-design on NPM + License: MIT + Code quality on DeepScan + Open issues tagged pkg:new-design + All Contributors +

Follow @freesewing_org on Twitter + Chat with us on Discord + Become a FreeSewing Patron + Follow @freesewing_org on Twitter +

+ +# @freesewing/new-design + +Initializer package for a new FreeSewing design: npx @freesewing/new-design + + + +## What am I looking at? πŸ€” + +This repository is our *monorepo* +holding [all our NPM packages](https://freesewing.dev/reference/packages/). + +This folder holds: @freesewing/new-design + +If you're not entirely sure what to do or how to start, type this command: + +``` +npm run tips +``` + +## About FreeSewing πŸ’€ + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate +our sewing patterns adapted to your measurements. + +If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/). +Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox +for parametric design of sewing patterns. But we also provide a range +of [plugins](https://freesewing.dev/reference/plugins/) that further extend the +functionality of the platform. + +If you have NodeJS installed, you can try it right now by running: + +```bash +npx create-freesewing-pattern +``` + +Or, consult our getting started guides +for [Linux](https://freesewing.dev/tutorials/getting-started-linux/), +[MacOS](https://freesewing.dev/tutorials/getting-started-mac/), +or [Windows](https://freesewing.dev/tutorials/getting-started-windows/). + +We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that +walks you through your first parametric design, +and [a friendly community](https://freesewing.org/community/where/) with +people who can help you when you get stuck. + +## Support FreeSewing: Become a patron πŸ₯° + +FreeSewing is an open source project run by a community, +and financially supported by our patrons. + +If you feel what we do is worthwhile, and you can spend a few coind without +hardship, then you should [join us and become a patron](https://freesewing.org/community/join). + +## Links πŸ‘©β€πŸ’» + + - πŸ’» Makers website: [freesewing.org](https://freesewing.org) + - πŸ’» Developers website: [freesewing.dev](https://freesewing.dev) + - πŸ’¬ Chat: On Discord via [discord.freesewing.org](https://discord.freesewing.org/) + - βœ… Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/) + - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) + - πŸ“· Instagram: [@freesewing_org](https://instagram.com/freesewing_org) + +## License: MIT πŸ€“ + +Β© [Joost De Cock](https://github.com/joostdecock). +See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details. + +## Where to get help 🀯 + +Our [chatrooms on Discord](https://chat.freesewing.org/) are the best place to ask questions, +share your feedback, or just hang out. + +If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new). + + + +## Contributors ✨ + +Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Adam Tomkins

πŸ“–

Alexandre Ignjatovic

πŸ’»

AlfaLyr

πŸ’» πŸ”Œ 🎨

Andrew James

πŸ“–

Anneke

πŸ“– 🌍

Annie Kao

πŸ“–

Anternative

πŸ“–

Anthony

πŸ’¬

Cameron Dubas

πŸ“–

Carsten Biebricher

πŸ“–

Cathy Zoller

πŸ“–

Chantal Lapointe

🌍

Damien PIQUET

πŸ’»

Darigov Research

πŸ“– πŸ€”

Elena FdR

πŸ“– πŸ“

Emmanuel Nyachoke

πŸ’» πŸ“–

Enoch Riese

πŸ’»

EvEkSwed

🌍

Fantastik-Maman

🌍

Forrest O.

πŸ“–

FrΓ©dΓ©ric

🌍

Glenn Matthews

πŸ“–

Igor Couto

πŸ›

Ikko Ashimine

πŸ“–

Irapeke

🌍

Jacek Sawoszczuk

πŸ“–

Jason Williams

πŸ“–

Jeremy Jackson

πŸ’»

Joebidido

🌍

Joost De Cock

🚧

Josh Essman

πŸ“–

Kake

πŸ“–

Kapunahele Wong

πŸ“–

Karen

πŸ“– πŸ“‹

Katie McGinley

πŸ“–

Kieran Klaassen

πŸ’»

Kittycatou

🌍

Kris

πŸ“–

Kristin Ruben

πŸ’»

Loudepeuter

🌍

Lucian

πŸ“‹

Marcus

🌍

Martin Tribo

πŸ“–

Nadege Michel

⚠️ πŸ“–

Natalia

πŸ’» 🎨 πŸ“

Nathan Yergler

πŸ“–

Nick Dower

πŸ“– πŸ’» πŸ›

Patrick Forringer

πŸ”Œ

Paul

πŸ“– πŸ“ 🌍

Phillip Thelen

πŸ’»

Pixieish

πŸ“–

Prof. dr. Sorcha NΓ­ Dhubhghaill

πŸ“–

Quentin FELIX

πŸ’» 🎨

Rik Hekker

πŸ›

Sam Livingston-Gray

πŸ“–

Sanne

πŸ’» πŸ“–

Sara Latorre

🌍

SeaZeeZee

πŸ“– πŸ’»

Slylele

πŸ“– 🌍

Soazillon

🌍

SoneaTheBest

🌍

Stefan Sydow

🌍 πŸ“– πŸ’»

TrΓ­ona

πŸ“–

Unmutual

πŸ“–

Wouter van Wageningen

πŸ’» 🎨 πŸ”§

amysews

πŸ“–

beautifulsummermoon

🌍

berce

πŸ“–

biou

πŸ’»

bobgeorgethe3rd

πŸ’» πŸ“– 🎨

brmlyklr

πŸ“–

chri5b

πŸ’» ⚠️

dingcycle

🌍

drowned-in-books

πŸ’¬

econo202

πŸ“–

ericamattos

🌍

fightingrabbit

πŸ’»

gaylyndie

πŸ“–

grimlokason

πŸ’»

hellgy

🎨

jackseye

πŸ“–

marckiesel

🌍

mesil

πŸ›

starfetch

πŸ’» πŸ“– 🌍 🎨

ttimearl

πŸ–‹

tuesgloomsday

πŸ“–

valadaptive

πŸ’»

viocky

🌍

woolishboy

πŸ’»

yc

🌍
+ + + + + + +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! + diff --git a/packages/new-design/build.js b/packages/new-design/build.js new file mode 100644 index 00000000000..67c80e27137 --- /dev/null +++ b/packages/new-design/build.js @@ -0,0 +1,55 @@ +/* This script will build the package with esbuild */ +const esbuild = require('esbuild') +const pkg = require('./package.json') + +// Create banner based on package info +const banner = `/** + * ${pkg.name} | v${pkg.version} + * ${pkg.description} + * (c) ${new Date().getFullYear()} ${pkg.author} + * @license ${pkg.license} + */` + +// Shared esbuild options +const options = { + banner: { js: banner }, + bundle: true, + entryPoints: ['index.mjs'], + external: ["@freesewing"], + metafile: process.env.VERBOSE ? true : false, + minify: process.env.NO_MINIFY ? false : true, + sourcemap: true, +} + +// Different formats +const formats = { + cjs: "dist/index.js", + esm: "dist/index.mjs", +} + +// Let esbuild generate different formats +let result +(async () => { + for (const [format, outfile] of Object.entries(formats)) { + result = await esbuild + .build({ ...options, outfile, format }) + .catch(() => process.exit(1)) + } + + if (process.env.VERBOSE) { + const info = await esbuild.analyzeMetafile(result.metafile) + console.log(info) + } + + // Also build a version that has all dependencies bundled + // This makes it easy to run tests + await esbuild + .build({ + ...options, + outfile: 'tests/dist/index.mjs', + format: 'esm', + external: [], + }) + .catch(() => process.exit(1)) + +})() diff --git a/packages/new-design/index.mjs b/packages/new-design/index.mjs new file mode 100644 index 00000000000..bd79ef34527 --- /dev/null +++ b/packages/new-design/index.mjs @@ -0,0 +1,18 @@ +#!/usr/bin/env node +import { cli } from './lib/cli.mjs' + +cli() + +/* + + ___ ___ _ + | __| _ ___ ___/ __| _____ __ _(_)_ _ __ _ + | _| '_/ -_) -_)__ \/ -_) V V / | ' \/ _` | + |_||_| \___\___|___/\___|\_/\_/|_|_||_\__, | + ≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑≑|___/ + Come for the sewing patterns + Stay for the community + + + */ + diff --git a/packages/new-design/lib/cli.mjs b/packages/new-design/lib/cli.mjs new file mode 100644 index 00000000000..7b48b730ab3 --- /dev/null +++ b/packages/new-design/lib/cli.mjs @@ -0,0 +1,54 @@ +import path from 'path' +import chalk from 'chalk' +import commander from 'commander' +import { banner } from '../../../scripts/banner.mjs' +import { + checkNodeVersion, + getChoices, + createEnvironment, +} from './utils.mjs' + + +export const cli = async () => { + + // Make it pretty + console.log(banner+"\n") + + // Make sure we have a valid NodeJS version + checkNodeVersion() + + // Get user input + const choices = await getChoices() + + // Create environment from template + const result = createEnvironment(choices) +} + +/* + + + const dest = await createLibrary(params) + + console.log(` +πŸŽ‰ ${strings[params.language]['cfp.patternCreated']} ${chalk.bold(dest)} + +${strings[params.language]['cfp.runTheseCommands']}: + + πŸ‘‰ ${chalk.cyan(`cd ${path.join(params.shortName, 'example')} && ${params.manager} start`)} + +${strings[params.language]['cfp.startWebpack']} + +${strings[params.language]['cfp.devDocsAvailableAt']} + ${chalk.bold('https://freesewing.dev/')} + +${strings[params.language]['cfp.talkToUs']} + ${chalk.bold('https://discord.freesewing.org/')} + +` + ) + + return dest +} + + +*/ diff --git a/packages/new-design/lib/config.mjs b/packages/new-design/lib/config.mjs new file mode 100644 index 00000000000..35637b47f56 --- /dev/null +++ b/packages/new-design/lib/config.mjs @@ -0,0 +1,191 @@ +export const config = { + node: 14, // Minimum node version + repo: 'freesewing/freesewing', // Repository to download from + branch: 'develop', // Branch to download from + i18n: [ + 'account', + 'common', + 'patrons', + 'themes', + 'workbench', + 'errors', + 'i18n', + 'lab', + 'measurements', + 'optiongroups', + 'o_bella', + 'o_bent', + 'o_breanna', + 'o_brian', + 'o_titan', + 'parts', + 'plugin', + 'settings', + 'welcome', + ], + fetch: { + sites: [ + "shared/utils.mjs", + "shared/config/freesewing.mjs", + "shared/config/i18n.config.mjs", + "shared/config/next.mjs", + "shared/config/postcss.config.js", + "shared/config/tailwind.config.js", + "shared/prebuild/contributors.mjs", + "shared/hooks/useLocalStorage.js", + "shared/hooks/useTheme.js", + "shared/styles/code.css", + "shared/styles/globals.css", + "shared/styles/svg-freesewing-draft.css", + "shared/themes/dark.js", + "shared/themes/hax0r.js", + "shared/themes/index.js", + "shared/themes/lgbtq.js", + "shared/themes/light.js", + "shared/themes/runtime.js", + "shared/themes/trans.js", + "shared/components/copy-to-clipboard.js", + "shared/components/json.js", + "shared/components/lightbox.js", + "shared/components/locale-picker.js", + "shared/components/modal.js", + "shared/components/page-link.js", + "shared/components/pinked-ribbon.js", + "shared/components/popout.js", + "shared/components/theme-picker.js", + "shared/components/web-link.js", + "shared/components/yaml.js", + "shared/components/layouts/default.js", + "shared/components/icons/box.js", + "shared/components/icons/camera.js", + "shared/components/icons/clear.js", + "shared/components/icons/close.js", + "shared/components/icons/cog.js", + "shared/components/icons/community.js", + "shared/components/icons/copy.js", + "shared/components/icons/design.js", + "shared/components/icons/discord.js", + "shared/components/icons/docs.js", + "shared/components/icons/down.js", + "shared/components/icons/edit.js", + "shared/components/icons/export.js", + "shared/components/icons/facebook.js", + "shared/components/icons/filter.js", + "shared/components/icons/freesewing.js", + "shared/components/icons/github.js", + "shared/components/icons/google.js", + "shared/components/icons/guide.js", + "shared/components/icons/heart.js", + "shared/components/icons/help.js", + "shared/components/icons/i18n.js", + "shared/components/icons/instagram.js", + "shared/components/icons/left.js", + "shared/components/icons/menu.js", + "shared/components/icons/note.js", + "shared/components/icons/options.js", + "shared/components/icons/page-size.js", + "shared/components/icons/page.js", + "shared/components/icons/print.js", + "shared/components/icons/reddit.js", + "shared/components/icons/right.js", + "shared/components/icons/rss.js", + "shared/components/icons/search.js", + "shared/components/icons/settings.js", + "shared/components/icons/theme.js", + "shared/components/icons/tip.js", + "shared/components/icons/tutorial.js", + "shared/components/icons/twitter.js", + "shared/components/icons/user.js", + "shared/components/icons/versions.js", + "shared/components/icons/with-breasts.js", + "shared/components/icons/without-breasts.js", + "shared/components/icons/xray.js", + "shared/components/logos/cc-by.js", + "shared/components/logos/cc.js", + "shared/components/logos/freesewing.js", + "shared/components/logos/osi.js", + "shared/components/navigation/aside.js", + "shared/components/navigation/primary.js", + "shared/components/robot/index.js", + "shared/components/robot/poses.js", + "shared/components/wrappers/img.js", + "shared/components/wrappers/mdx.js", + "shared/components/wrappers/page.js", + "shared/components/wrappers/toc.js", + "shared/components/wrappers/workbench.js", + "shared/components/mdx/index.js", + "shared/components/workbench/default-settings.js", + "shared/components/workbench/events.js", + "shared/components/workbench/export.js", + "shared/components/workbench/json.js", + "shared/components/workbench/preload.js", + "shared/components/workbench/sample.js", + "shared/components/workbench/yaml.js", + "shared/components/workbench/inputs/design-option-count.js", + "shared/components/workbench/inputs/design-option-list.js", + "shared/components/workbench/inputs/design-option-pct-deg.js", + "shared/components/workbench/inputs/measurement.js", + "shared/components/workbench/measurements/index.js", + "shared/components/workbench/measurements/non-human.js", + "shared/components/workbench/draft/error.js", + "shared/components/workbench/draft/index.js", + "shared/components/workbench/draft/svg-wrapper.js", + "shared/components/workbench/draft/utils.js", + "shared/components/workbench/draft/circle/index.js", + "shared/components/workbench/draft/defs/index.js", + "shared/components/workbench/draft/part/index.js", + "shared/components/workbench/draft/path/index.js", + "shared/components/workbench/draft/point/index.js", + "shared/components/workbench/draft/snippet/index.js", + "shared/components/workbench/draft/svg/index.js", + "shared/components/workbench/draft/text/index.js", + "shared/components/workbench/draft/text-on-path/index.js", + "shared/components/workbench/layout/draft.js", + "shared/components/workbench/layout/cut/index.js", + "shared/components/workbench/layout/cut/settings.js", + "shared/components/workbench/layout/print/index.js", + "shared/components/workbench/layout/print/orientation-picker.js", + "shared/components/workbench/layout/print/pagesize-picker.js", + "shared/components/workbench/layout/print/plugin.js", + "shared/components/workbench/layout/print/settings.js", + "shared/components/workbench/menu/index.js", + "shared/components/workbench/menu/view.js", + "shared/components/workbench/menu/core-settings/core-setting-bool.js", + "shared/components/workbench/menu/core-settings/core-setting-list.js", + "shared/components/workbench/menu/core-settings/core-setting-mm.js", + "shared/components/workbench/menu/core-settings/core-setting-nr.js", + "shared/components/workbench/menu/core-settings/core-setting-only.js", + "shared/components/workbench/menu/core-settings/core-setting-sa-bool.js", + "shared/components/workbench/menu/core-settings/core-setting-sa-mm.js", + "shared/components/workbench/menu/core-settings/index.js", + "shared/components/workbench/menu/core-settings/setting.js", + "shared/components/workbench/menu/design-options/index.js", + "shared/components/workbench/menu/design-options/option-group.js", + "shared/components/workbench/menu/design-options/option-input.js", + "shared/components/workbench/menu/design-options/option-value.js", + "shared/components/workbench/menu/design-options/option.js", + "shared/components/workbench/menu/test-design-options/index.js", + "shared/components/workbench/menu/test-design-options/option-group.js", + "shared/components/workbench/menu/test-design-options/option-sub-group.js", + "shared/components/workbench/menu/test-design-options/option.js", + "shared/components/workbench/menu/xray/attributes.js", + "shared/components/workbench/menu/xray/disable.js", + "shared/components/workbench/menu/xray/index.js", + "shared/components/workbench/menu/xray/list.js", + "shared/components/workbench/menu/xray/log.js", + "shared/components/workbench/menu/xray/path-ops.js", + "shared/components/workbench/menu/xray/path.js", + "shared/components/workbench/menu/xray/point.js", + "shared/components/workbench/menu/xray/reset.js", + "lab/components/footer.js", + "lab/components/wrappers/layout.js", + "lab/components/wrappers/page.js" + ], + config: [ + { + from: 'measurements.mjs', + to: 'shared/config/measurements.mjs' + } + ], + } +} diff --git a/packages/new-design/lib/download-list.js b/packages/new-design/lib/download-list.js new file mode 100644 index 00000000000..c3cab9a77b0 --- /dev/null +++ b/packages/new-design/lib/download-list.js @@ -0,0 +1,43 @@ +import rdir from 'recursive-readdir' +import { join, basename } from 'path' + +// Files to not download +const avoid = { + files: [ + 'README.md', + 'package.json', + 'CHANGELOG.md', + 'version-pickers.js', + 'pattern-picker.js', + 'header.js', + ], + dirs: [ 'node_modules', 'layouts' ] +} + + +// Method to check what files to keep +const keep = file => { + if (avoid.files.indexOf(basename(file)) !== -1) return false + for (const dir of avoid.dirs) { + if (file.indexOf(dir) !== -1) return false + } + + return true +} + +const getFiles = async (site) => { + const all = await rdir(join('..', '..', 'sites', site)) + + return all + .filter(file => keep(file)) + .map(file => file.slice(12)) +} + +getFiles('shared').then(shared => { + getFiles(join('lab', 'components')).then(lab => { + console.log(JSON.stringify([ + ...shared, + ...lab, + ], null, 2)) + }) +}) diff --git a/packages/new-design/lib/utils.mjs b/packages/new-design/lib/utils.mjs new file mode 100644 index 00000000000..3d90eec9162 --- /dev/null +++ b/packages/new-design/lib/utils.mjs @@ -0,0 +1,259 @@ +import { config } from './config.mjs' +import { mkdir, readFile, writeFile, copyFile } from 'node:fs/promises' +import { join, resolve, dirname, extname } from 'path' +import mustache from 'mustache' +import rdir from 'recursive-readdir' +import chalk from 'chalk' +import prompts from 'prompts' +import {oraPromise} from 'ora' +import { execa } from 'execa' +import axios from 'axios' + +const nl = "\n" +const tab = " " +const nlt = nl+tab + +// Checks for node 14 or higher +export const checkNodeVersion = () => { + const node_version = process.version.slice(1).split('.')[0] + if (parseInt(node_version) < config.node) { + console.log( + chalk.yellow(nlt+`⚠️ FreeSewing requires Node v${config.node} or newer`) + + nl+nlt+'We hightly recommend using NVM to manage your Node versions:' + + nlt+chalk.blue('https://github.com/nvm-sh/nvm') + + nl+nlt+'When in doubt, pick an active LTS version:' + + nlt+chalk.blue('https://nodejs.org/en/about/releases/')+nl+nl + ) + process.exit(1) + } +} + +// Helper method to validate the design name +const validateDesignName = (name) => { + if (/^([a-z]+)$/.test(name)) return true + else return ' πŸ™ˆ Please use only [a-z], no spaces, no capitals, no nothing 🀷' +} + +// Gets user input to figure out what to do +export const getChoices = async () => { + + const { template } = await prompts({ + type: 'select', + name: 'template', + message: 'What template would you like to use? πŸ“‘', + choices: [ + { title: 'From Scratch', value: 'scratch', description: 'Create a design from scratch' }, + { title: 'Extend Brian', value: 'brian', description: "Extend the Brian design (basic torso block for menswear)" }, + { title: 'Extend Bent', value: 'bent', description: "Extend the Bent design (like brian with added two-part sleeve)" }, + { title: 'Extend Bella', value: 'bella', description: "Extend the Bella design (womenswear torso block)" }, + { title: 'Extend Breanna', value: 'breanna', description: "Extend the Breanna design (womenswear torso block - YMMV)" }, + { title: 'Extend Titan', value: 'titan', description: "Extend the Titan design (gender-neutral trouser block)" }, + ], + initial: 0, + }) + + const { name } = await prompts({ + type: 'text', + name: 'name', + message: 'What name would you like the design to have? 🏷️ ([a-z] only)', + validate: validateDesignName, + }) + + const { manager } = await prompts({ + type: 'select', + name: 'manager', + message: 'Last but not least, what package manager do you use? πŸ“¦', + choices: [ + { title: 'yarn', value: 'yarn', description: 'Yarn - Nice if you have it' }, + { title: 'npm', value: 'npm', description: "NPM - Comes with NodeJS" }, + ], + initial: 0, + }) + + return { template, name, manager } +} + +// Keep track of directories that need to be created +const dirs = {} +const ensureDir = async (file, suppress=false) => { + const dir = suppress + ? dirname(file.replace(suppress)) + : dirname(file) + if (!dirs[dir]) { + await mkdir(dir, { recursive: true }) + dirs[dir] = true + } +} + +// Helper method to copy template files +const copyTemplate = async (config, choices) => { + + // Copy files in parallel rather than using await + const promises = [] + + // Copy shared files + for (const from of config.files.shared) { + const to = config.dest + from.slice(config.source.shared.length) + if (!dirs[to]) await ensureDir(to) + console.log(to) + promises.push(copyFile(from, to)) + } + + // Template files + for (const from of config.files.template) { + const to = config.dest + from.slice(config.source.template.length) + if (!dirs[to]) await ensureDir(to) + if (extname(from) === '.json') { + // Template out package.json + const src = await readFile(from, 'utf-8') + promises.push( + writeFile(to, mustache.render(src, { name: choices.name })) + ) + } else { + // Just copy the file + promises.push(copyFile(from, to)) + } + } + + await Promise.all(promises) + + return +} + +// Helper method to run [yarn|npm] install +const installDependencies = async (config, choices) => await execa( + `${choices.manager} install`, + { + cwd: config.dest, + shell: true + } +) + +// Helper method to download web environment +const downloadLabFiles = async (config) => { + const base = 'https://raw.githubusercontent.com' + const promises = [] + for (const dir in config.fetch) { + for (const file of config.fetch[dir]) { + const to = (typeof file === 'string') + ? join(config.dest, file) + : join(config.dest, file.to) + if (!dirs[to]) await ensureDir(to) + console.log(to) + promises.push( + axios.get(`${base}/${config.repo}/${config.branch}/${dir}/${typeof file === 'string' ? file : file.from}`) + .catch(err => console.log(err)) + .then(res => promises.push(writeFile(to, res.data))) + ) + } + } + + await Promise.all(promises) + + return +} + +// Creates the environment based on the user's choices +export const createEnvironment = async (choices) => { + + // Store directories for re-use + config.cwd = process.cwd() + config.source = { + root: dirname(process.argv[1]), + template: dirname(process.argv[1]) + `/templates/from-${choices.template}`, + shared: dirname(process.argv[1]) + `/shared` + } + config.dest = join(config.cwd, choices.name) + + // Create target directory + await mkdir(config.dest, { recursive: true }) + + // Find files + config.files = { + template: await rdir(config.source.template), + shared: await rdir(config.source.shared), + } + + // Copy/Template files + await copyTemplate(config, choices) + + // Install dependencies + await oraPromise( + installDependencies(config, choices), + chalk.white.bold('Installing dependencies')+chalk.white.dim(' (This will take a while)') + ) + + // Fetch web components + await oraPromise( + downloadLabFiles(config), + chalk.white.bold('Downloading web components')+chalk.white.dim(' (This too will take a while)') + ) + +} + +//const handlebars = require('handlebars') +//const execa = require('execa') +//const fs = require('fs') +//const globby = require('globby') +//const normalize = require('normalize-path') +//const mkdirp = require('make-dir') +//const ora = require('ora') +//const pEachSeries = require('p-each-series') + +//const pkg = require('../package') +/* +const templateBlacklist = new Set([path.join('example', 'public', 'favicon.ico')]) + +module.exports = async (info) => { + + + + + + if (git) { + const promise = module.exports.initGitRepo({ dest }) + ora.promise(promise, 'Initializing git repo') + await promise + } + + + return dest +} + +module.exports.initGitRepo = async (opts) => { + const { dest } = opts + + const gitIgnorePath = path.join(dest, '.gitignore') + fs.writeFileSync( + gitIgnorePath, + ` +# See https://help.github.com/ignore-files/ for more about ignoring files. + +# dependencies +node_modules + +# builds +build +dist +.rpt2_cache + +# misc +.DS_Store +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +`, + 'utf8' + ) + + const cmd = `git init && git add . && git commit -m ":tada: Initialized ${pkg.name}@${pkg.version} with create-freesewing-pattern"` + return execa.sync(cmd, { cwd: dest, shell: true }) +} + +*/ diff --git a/packages/new-design/package.json b/packages/new-design/package.json new file mode 100644 index 00000000000..f06ca245e09 --- /dev/null +++ b/packages/new-design/package.json @@ -0,0 +1,57 @@ +{ + "name": "@freesewing/new-design", + "version": "2.21.0-rc.0", + "description": "Initializer package for a new FreeSewing design: npx @freesewing/new-design", + "author": "Joost De Cock (https://github.com/joostdecock)", + "homepage": "https://freesewing.org/", + "repository": "github:freesewing/freesewing", + "license": "MIT", + "bugs": { + "url": "https://github.com/freesewing/freesewing/issues" + }, + "funding": { + "type": "individual", + "url": "https://freesewing.org/patrons/join" + }, + "keywords": [ + "freesewing", + "freesewing" + ], + "main": "dist/index.js", + "module": "dist/index.mjs", + "scripts": { + "build": "SITE=new-design/shared node ../../sites/shared/prebuild/i18n-only.mjs", + "clean": "rimraf dist", + "mbuild": "NO_MINIFY=1 node build.js", + "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", + "test": "echo \"new-design: No tests configured. Perhaps you'd like to do this?\" && exit 0", + "vbuild": "VERBOSE=1 node build.js", + "lab": "cd ../../sites/lab && yarn start", + "tips": "node ../../scripts/help.mjs", + "cibuild_step6": "node build.js" + }, + "peerDependencies": {}, + "dependencies": { + "axios": "^0.27.2", + "chalk": "^5.0.1", + "execa": "^6.1.0", + "mustache": "^4.2.0", + "ora": "^6.1.0", + "prompts": "^2.4.2", + "recursive-readdir": "^2.2.2" + }, + "devDependencies": {}, + "files": [ + "dist/*", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public", + "tag": "next" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6" + } +} diff --git a/packages/new-design/shared/lab/components/header.js b/packages/new-design/shared/lab/components/header.js new file mode 100644 index 00000000000..9730bd9b8b9 --- /dev/null +++ b/packages/new-design/shared/lab/components/header.js @@ -0,0 +1,100 @@ +import { useState, useEffect } from 'react' +import Logo from 'shared/components/logos/freesewing.js' +import Link from 'next/link' +import ThemePicker from 'shared/components/theme-picker.js' +import LocalePicker from 'shared/components/locale-picker.js' +import CloseIcon from 'shared/components/icons/close.js' +import MenuIcon from 'shared/components/icons/menu.js' +import DocsIcon from 'shared/components/icons/docs.js' +import HelpIcon from 'shared/components/icons/help.js' +import { useTranslation } from 'next-i18next' + +const Right = props => ( + + + +) +const Left = props => ( + + + +) + +const Header = ({ app }) => { + const { t } = useTranslation(['common']) + + const [prevScrollPos, setPrevScrollPos] = useState(0) + const [show, setShow] = useState(true) + + useEffect(() => { + if (typeof window !== 'undefined') { + const handleScroll = () => { + const curScrollPos = (typeof window !== 'undefined') ? window.pageYOffset : 0 + if (curScrollPos >= prevScrollPos) { + if (show && curScrollPos > 20) setShow(false) + } + else setShow(true) + setPrevScrollPos(curScrollPos) + } + window.addEventListener('scroll', handleScroll) + return () => window.removeEventListener('scroll', handleScroll) + } + }, [prevScrollPos, show]) + + + return ( +
+
+
+ +
+ + {t('docs')} + + + + {t('support')} + + +
+
+ + + FreeSewing + + +
+
+ + +
+
+
+
+ ) +} + +export default Header diff --git a/packages/new-design/shared/lab/components/layouts/bare.js b/packages/new-design/shared/lab/components/layouts/bare.js new file mode 100644 index 00000000000..f7a390a90eb --- /dev/null +++ b/packages/new-design/shared/lab/components/layouts/bare.js @@ -0,0 +1,69 @@ +import React from 'react' +import { useRouter } from 'next/router' +import Link from 'next/link' +// Shared components +import Logo from 'shared/components/logos/freesewing.js' +import Aside from 'shared/components/navigation/aside' +import get from 'lodash.get' +import { BeforeNav } from './lab' + +const PageTitle = ({ app, slug, title }) => { + if (title) return

{title}

+ if (slug) return

{get(app.navigation, slug.split('/')).__title}

+ + return

FIXME: This page has no title

+} + +const Breadcrumbs = ({ app, slug=false, title }) => { + if (!slug) return null + const crumbs = [] + const chunks = slug.split('/') + for (const i in chunks) { + const j = parseInt(i)+parseInt(1) + const page = get(app.navigation, chunks.slice(0,j)) + if (page) crumbs.push([page.__linktitle, '/'+chunks.slice(0,j).join('/'), (j < chunks.length)]) + } + + return ( + + ) +} + +const DefaultLayout = ({ app, title=false, children=[] }) => { + const router = useRouter() + const slug = router.asPath.slice(1) + + return ( + <> +