wip(new-design): Work on v3 for this package
This commit is contained in:
parent
3604cb918d
commit
3553c43633
40 changed files with 364 additions and 1753 deletions
|
@ -11,6 +11,6 @@ export const cli = async () => {
|
||||||
// Get user input
|
// Get user input
|
||||||
const choices = await getChoices()
|
const choices = await getChoices()
|
||||||
|
|
||||||
// Create environment from template
|
// Create environment
|
||||||
createEnvironment(choices)
|
createEnvironment(choices)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ export const config = {
|
||||||
// Whether we're publishing next or latest tags
|
// Whether we're publishing next or latest tags
|
||||||
tag: 'next',
|
tag: 'next',
|
||||||
// Minimum node version
|
// Minimum node version
|
||||||
node: 16,
|
node: 18,
|
||||||
// Site to download from
|
// Site to download from
|
||||||
fileUri: 'https://raw.githubusercontent.com',
|
fileUri: 'https://raw.githubusercontent.com',
|
||||||
// Repository to download from
|
// Repository to download from
|
||||||
|
@ -19,7 +19,7 @@ export const config = {
|
||||||
'workbench',
|
'workbench',
|
||||||
'errors',
|
'errors',
|
||||||
'i18n',
|
'i18n',
|
||||||
'lab',
|
'sde',
|
||||||
'measurements',
|
'measurements',
|
||||||
'optiongroups',
|
'optiongroups',
|
||||||
'o_bella',
|
'o_bella',
|
||||||
|
@ -54,8 +54,6 @@ npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
# e2e test results
|
|
||||||
playwright-report
|
|
||||||
`,
|
`,
|
||||||
fetch: {
|
fetch: {
|
||||||
config: [
|
config: [
|
||||||
|
@ -65,176 +63,161 @@ playwright-report
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
sites: [
|
sites: [
|
||||||
'shared/utils.mjs',
|
{
|
||||||
'shared/designs/index.js',
|
from: 'sde/env.local',
|
||||||
'shared/config/freesewing.mjs',
|
to: 'sde/.env.local',
|
||||||
|
},
|
||||||
|
'sde/i18n.config.mjs',
|
||||||
|
'sde/next-i18next.config.js',
|
||||||
|
'sde/next.config.mjs',
|
||||||
|
'sde/package.json',
|
||||||
|
'sde/postcss.config.js',
|
||||||
|
'sde/site.config.mjs',
|
||||||
|
'sde/tailwind.config.mjs',
|
||||||
|
'sde/hooks/use-design.mjs',
|
||||||
|
'sde/components/dynamic-org-docs.mjs',
|
||||||
|
'sde/components/feeds.mjs',
|
||||||
|
'sde/components/search.mjs',
|
||||||
|
'sde/components/header/design-picker.mjs',
|
||||||
|
'sde/components/header/index.mjs',
|
||||||
|
'sde/components/navigation/modal-menu.mjs',
|
||||||
|
'sde/components/layouts/bare.mjs',
|
||||||
|
'sde/components/layouts/default.mjs',
|
||||||
|
'sde/components/layouts/workbench.mjs',
|
||||||
|
'sde/components/wrappers/page.mjs',
|
||||||
|
'sde/design/from-bent/src/back.mjs',
|
||||||
|
'sde/design/from-bent/src/front.mjs',
|
||||||
|
'sde/design/from-bent/src/index.mjs',
|
||||||
|
'sde/design/from-bent/src/top-sleeve.mjs',
|
||||||
|
'sde/design/from-bent/src/under-sleeve.mjs',
|
||||||
|
'sde/design/from-bent/i18n/de.json',
|
||||||
|
'sde/design/from-bent/i18n/en.json',
|
||||||
|
'sde/design/from-bent/i18n/es.json',
|
||||||
|
'sde/design/from-bent/i18n/fr.json',
|
||||||
|
'sde/design/from-bent/i18n/index.mjs',
|
||||||
|
'sde/design/from-bent/i18n/nl.json',
|
||||||
|
'sde/design/from-bent/i18n/uk.json',
|
||||||
|
'sde/design/from-bella/en.json',
|
||||||
|
'sde/design/from-bella/src/back.mjs',
|
||||||
|
'sde/design/from-bella/src/front.mjs',
|
||||||
|
'sde/design/from-bella/src/index.mjs',
|
||||||
|
'sde/design/from-bella/i18n/de.json',
|
||||||
|
'sde/design/from-bella/i18n/en.json',
|
||||||
|
'sde/design/from-bella/i18n/es.json',
|
||||||
|
'sde/design/from-bella/i18n/fr.json',
|
||||||
|
'sde/design/from-bella/i18n/index.mjs',
|
||||||
|
'sde/design/from-bella/i18n/nl.json',
|
||||||
|
'sde/design/from-bella/i18n/uk.json',
|
||||||
|
'sde/design/from-breanna/src/back.mjs',
|
||||||
|
'sde/design/from-breanna/src/front.mjs',
|
||||||
|
'sde/design/from-breanna/src/index.mjs',
|
||||||
|
'sde/design/from-breanna/src/sleeve.mjs',
|
||||||
|
'sde/design/from-breanna/i18n/de.json',
|
||||||
|
'sde/design/from-breanna/i18n/en.json',
|
||||||
|
'sde/design/from-breanna/i18n/es.json',
|
||||||
|
'sde/design/from-breanna/i18n/fr.json',
|
||||||
|
'sde/design/from-breanna/i18n/index.mjs',
|
||||||
|
'sde/design/from-breanna/i18n/nl.json',
|
||||||
|
'sde/design/from-breanna/i18n/uk.json',
|
||||||
|
'sde/design/from-brian/i18n/de.json',
|
||||||
|
'sde/design/from-brian/i18n/en.json',
|
||||||
|
'sde/design/from-brian/i18n/es.json',
|
||||||
|
'sde/design/from-brian/i18n/fr.json',
|
||||||
|
'sde/design/from-brian/i18n/index.mjs',
|
||||||
|
'sde/design/from-brian/i18n/nl.json',
|
||||||
|
'sde/design/from-brian/i18n/uk.json',
|
||||||
|
'sde/design/from-brian/src/back.mjs',
|
||||||
|
'sde/design/from-brian/src/front.mjs',
|
||||||
|
'sde/design/from-brian/src/index.mjs',
|
||||||
|
'sde/design/from-brian/src/sleeve.mjs',
|
||||||
|
'sde/design/from-titan/i18n/de.json',
|
||||||
|
'sde/design/from-titan/i18n/en.json',
|
||||||
|
'sde/design/from-titan/i18n/es.json',
|
||||||
|
'sde/design/from-titan/i18n/fr.json',
|
||||||
|
'sde/design/from-titan/i18n/index.mjs',
|
||||||
|
'sde/design/from-titan/i18n/nl.json',
|
||||||
|
'sde/design/from-titan/i18n/uk.json',
|
||||||
|
'sde/design/from-titan/src/back.mjs',
|
||||||
|
'sde/design/from-titan/src/front.mjs',
|
||||||
|
'sde/design/from-titan/src/index.mjs',
|
||||||
|
'sde/design/from-scratch/i18n/de.json',
|
||||||
|
'sde/design/from-scratch/i18n/en.json',
|
||||||
|
'sde/design/from-scratch/i18n/es.json',
|
||||||
|
'sde/design/from-scratch/i18n/fr.json',
|
||||||
|
'sde/design/from-scratch/i18n/index.mjs',
|
||||||
|
'sde/design/from-scratch/i18n/nl.json',
|
||||||
|
'sde/design/from-scratch/i18n/uk.json',
|
||||||
|
'sde/design/from-scratch/src/index.mjs',
|
||||||
|
'sde/design/from-scratch/src/scratch.mjs',
|
||||||
|
'sde/design/tutorial/i18n/de.json',
|
||||||
|
'sde/design/tutorial/i18n/en.json',
|
||||||
|
'sde/design/tutorial/i18n/es.json',
|
||||||
|
'sde/design/tutorial/i18n/fr.json',
|
||||||
|
'sde/design/tutorial/i18n/index.mjs',
|
||||||
|
'sde/design/tutorial/i18n/nl.json',
|
||||||
|
'sde/design/tutorial/i18n/uk.json',
|
||||||
|
'sde/design/tutorial/src/bib.mjs',
|
||||||
|
'sde/design/tutorial/src/index.mjs',
|
||||||
|
'sde/public/brands/algolia.svg',
|
||||||
|
'sde/public/brands/bugsnag.svg',
|
||||||
|
'sde/public/brands/crowdin.svg',
|
||||||
|
'sde/public/brands/netlify.svg',
|
||||||
|
'sde/public/brands/vercel.svg',
|
||||||
|
'sde/pages/_app.mjs',
|
||||||
|
'sde/pages/design.mjs',
|
||||||
|
'sde/pages/index.mjs',
|
||||||
|
'sde/pages/support.mjs',
|
||||||
|
'sde/pages/code/index.mjs',
|
||||||
|
'sde/pages/design/[design].mjs',
|
||||||
|
'sde/pages/docs/index.mjs',
|
||||||
|
'sde/pages/sde/en.yaml',
|
||||||
|
'sde/pages/sde/index.mjs',
|
||||||
|
'sde/pages/sets/[id].mjs',
|
||||||
|
'sde/pages/signup/index.mjs',
|
||||||
|
'sde/pages/patterns/index.mjs',
|
||||||
|
'sde/pages/patterns/[id]/edit.mjs',
|
||||||
|
'sde/pages/patterns/[id]/index.mjs',
|
||||||
|
'sde/pages/signin/index.mjs',
|
||||||
|
'sde/pages/signin/callback/[provider].mjs',
|
||||||
|
'sde/pages/account/[platform].mjs',
|
||||||
|
'sde/pages/account/bio.mjs',
|
||||||
|
'sde/pages/account/compare.mjs',
|
||||||
|
'sde/pages/account/consent.mjs',
|
||||||
|
'sde/pages/account/control.mjs',
|
||||||
|
'sde/pages/account/email.mjs',
|
||||||
|
'sde/pages/account/export.mjs',
|
||||||
|
'sde/pages/account/github.mjs',
|
||||||
|
'sde/pages/account/img.mjs',
|
||||||
|
'sde/pages/account/index.mjs',
|
||||||
|
'sde/pages/account/language.mjs',
|
||||||
|
'sde/pages/account/mfa.mjs',
|
||||||
|
'sde/pages/account/newsletter.mjs',
|
||||||
|
'sde/pages/account/password.mjs',
|
||||||
|
'sde/pages/account/privacy.mjs',
|
||||||
|
'sde/pages/account/reload.mjs',
|
||||||
|
'sde/pages/account/remove.mjs',
|
||||||
|
'sde/pages/account/restrict.mjs',
|
||||||
|
'sde/pages/account/units.mjs',
|
||||||
|
'sde/pages/account/username.mjs',
|
||||||
|
'sde/pages/account/apikeys/[id].mjs',
|
||||||
|
'sde/pages/account/apikeys/index.mjs',
|
||||||
|
'sde/pages/account/bookmarks/[id].mjs',
|
||||||
|
'sde/pages/account/bookmarks/index.mjs',
|
||||||
|
'sde/pages/account/sets/[id].mjs',
|
||||||
|
'sde/pages/account/sets/index.mjs',
|
||||||
|
'sde/pages/account/patterns/index.mjs',
|
||||||
|
'sde/pages/account/patterns/[id]/edit.mjs',
|
||||||
|
'sde/pages/account/patterns/[id]/index.mjs',
|
||||||
|
'shared/config/cloudflare.mjs',
|
||||||
|
'shared/config/designs.mjs',
|
||||||
|
'shared/config/freesewing.config.mjs',
|
||||||
'shared/config/i18n.config.mjs',
|
'shared/config/i18n.config.mjs',
|
||||||
'shared/config/next.mjs',
|
'shared/config/next.mjs',
|
||||||
|
'shared/config/paypal.mjs',
|
||||||
|
'shared/config/playwright.mjs',
|
||||||
'shared/config/postcss.config.js',
|
'shared/config/postcss.config.js',
|
||||||
'shared/config/tailwind-force.html',
|
'shared/config/tailwind-force.html',
|
||||||
'shared/config/tailwind.config.js',
|
'shared/config/tailwind.config.mjs',
|
||||||
'shared/hooks/useGist.mjs',
|
|
||||||
'shared/hooks/useLocalStorage.mjs',
|
|
||||||
'shared/hooks/useTheme.mjs',
|
|
||||||
'shared/mdx/compiler.mjs',
|
|
||||||
'shared/mdx/loader.mjs',
|
|
||||||
'shared/mdx/mdx-plugin-toc.mjs',
|
|
||||||
'shared/mdx/remark-intro-plugin.mjs',
|
|
||||||
'shared/strapi/loader.js',
|
|
||||||
'shared/strapi/qa.mjs',
|
|
||||||
'shared/themes/dark.js',
|
|
||||||
'shared/themes/hax0r.js',
|
|
||||||
'shared/themes/index.js',
|
|
||||||
'shared/themes/lgbtq.js',
|
|
||||||
'shared/themes/light.js',
|
|
||||||
'shared/themes/runtime.mjs',
|
|
||||||
'shared/styles/code.css',
|
|
||||||
'shared/styles/globals.css',
|
|
||||||
'shared/styles/svg-freesewing-draft.css',
|
|
||||||
'shared/prebuild/contributors.mjs',
|
|
||||||
'shared/prebuild/feed.mjs',
|
|
||||||
'shared/prebuild/i18n-only.mjs',
|
|
||||||
'shared/prebuild/i18n.mjs',
|
|
||||||
'shared/prebuild/index.mjs',
|
|
||||||
'shared/prebuild/lab.mjs',
|
|
||||||
'shared/prebuild/md-intro.mjs',
|
|
||||||
'shared/prebuild/mdx.mjs',
|
|
||||||
'shared/prebuild/navigation.mjs',
|
|
||||||
'shared/prebuild/patrons.mjs',
|
|
||||||
'shared/prebuild/strapi.mjs',
|
|
||||||
'shared/prebuild/og/index.mjs',
|
|
||||||
'shared/components/breadcrumbs.mjs',
|
|
||||||
'shared/components/code.mjs',
|
|
||||||
'shared/components/copy-to-clipboard.mjs',
|
|
||||||
'shared/components/docs-link.mjs',
|
|
||||||
'shared/components/icons.mjs',
|
|
||||||
'shared/components/json.mjs',
|
|
||||||
'shared/components/lightbox.mjs',
|
|
||||||
'shared/components/loader.mjs',
|
|
||||||
'shared/components/modal.mjs',
|
|
||||||
'shared/components/link.mjs',
|
|
||||||
'shared/components/picker.mjs',
|
|
||||||
'shared/components/popout.mjs',
|
|
||||||
'shared/components/raw-span.mjs',
|
|
||||||
'shared/components/ribbon.mjs',
|
|
||||||
'shared/components/spinner.mjs',
|
|
||||||
'shared/components/web-link.mjs',
|
|
||||||
'shared/components/wordmark.mjs',
|
|
||||||
'shared/components/worm.mjs',
|
|
||||||
'shared/components/yaml.mjs',
|
|
||||||
'shared/components/error/error-boundary.mjs',
|
|
||||||
'shared/components/error/reset-buttons.mjs',
|
|
||||||
'shared/components/error/view.mjs',
|
|
||||||
'shared/components/icons/flip.js',
|
|
||||||
'shared/components/icons/rotate.js',
|
|
||||||
'shared/components/locale-picker/index.mjs',
|
|
||||||
'shared/components/locale-picker/locales.de.yaml',
|
|
||||||
'shared/components/locale-picker/locales.en.yaml',
|
|
||||||
'shared/components/locale-picker/locales.es.yaml',
|
|
||||||
'shared/components/locale-picker/locales.fr.yaml',
|
|
||||||
'shared/components/locale-picker/locales.nl.yaml',
|
|
||||||
'shared/components/logos/cc-by.mjs',
|
|
||||||
'shared/components/logos/cc.mjs',
|
|
||||||
'shared/components/logos/freesewing.mjs',
|
|
||||||
'shared/components/logos/osi.mjs',
|
|
||||||
'shared/components/mdx/figure.mjs',
|
|
||||||
'shared/components/mdx/highlight.mjs',
|
|
||||||
'shared/components/mdx/http.mjs',
|
|
||||||
'shared/components/mdx/index.mjs',
|
|
||||||
'shared/components/mdx/mermaid.mjs',
|
|
||||||
'shared/components/mdx/prev-next.mjs',
|
|
||||||
'shared/components/mdx/read-more.mjs',
|
|
||||||
'shared/components/mdx/tabbed-example.mjs',
|
|
||||||
'shared/components/mdx/tabs.mjs',
|
|
||||||
'shared/components/mdx/youtube.mjs',
|
|
||||||
'shared/components/navigation/aside.mjs',
|
|
||||||
'shared/components/navigation/primary.mjs',
|
|
||||||
'shared/components/robot/index.mjs',
|
|
||||||
'shared/components/robot/poses.mjs',
|
|
||||||
'shared/components/theme-picker/index.mjs',
|
|
||||||
'shared/components/theme-picker/themes.de.yaml',
|
|
||||||
'shared/components/theme-picker/themes.en.yaml',
|
|
||||||
'shared/components/theme-picker/themes.es.yaml',
|
|
||||||
'shared/components/theme-picker/themes.fr.yaml',
|
|
||||||
'shared/components/theme-picker/themes.nl.yaml',
|
|
||||||
'shared/components/wrappers/img.mjs',
|
|
||||||
'shared/components/wrappers/mdx.mjs',
|
|
||||||
'shared/components/wrappers/page.mjs',
|
|
||||||
'shared/components/wrappers/toc.mjs',
|
|
||||||
'shared/components/wrappers/workbench.mjs',
|
|
||||||
'shared/components/workbench/gist.mjs',
|
|
||||||
'shared/components/workbench/logs.mjs',
|
|
||||||
'shared/components/workbench/preloaders.mjs',
|
|
||||||
'shared/components/workbench/sample.mjs',
|
|
||||||
'shared/components/workbench/edit/index.mjs',
|
|
||||||
'shared/components/workbench/edit/gist-validator.mjs',
|
|
||||||
'shared/components/workbench/exporting/export-handler.mjs',
|
|
||||||
'shared/components/workbench/exporting/export-worker.js',
|
|
||||||
'shared/components/workbench/exporting/index.mjs',
|
|
||||||
'shared/components/workbench/exporting/pdf-maker.mjs',
|
|
||||||
'shared/components/workbench/inputs/design-option-count.mjs',
|
|
||||||
'shared/components/workbench/inputs/design-option-list.mjs',
|
|
||||||
'shared/components/workbench/inputs/design-option-pct-deg.mjs',
|
|
||||||
'shared/components/workbench/inputs/measurement.mjs',
|
|
||||||
'shared/components/workbench/measurements/index.mjs',
|
|
||||||
'shared/components/workbench/draft/circle.mjs',
|
|
||||||
'shared/components/workbench/draft/defs.mjs',
|
|
||||||
'shared/components/workbench/draft/error.mjs',
|
|
||||||
'shared/components/workbench/draft/index.mjs',
|
|
||||||
'shared/components/workbench/draft/part.mjs',
|
|
||||||
'shared/components/workbench/draft/path.mjs',
|
|
||||||
'shared/components/workbench/draft/point.mjs',
|
|
||||||
'shared/components/workbench/draft/snippet.mjs',
|
|
||||||
'shared/components/workbench/draft/stack.mjs',
|
|
||||||
'shared/components/workbench/draft/svg.mjs',
|
|
||||||
'shared/components/workbench/draft/text.mjs',
|
|
||||||
'shared/components/workbench/draft/utils.mjs',
|
|
||||||
'shared/components/workbench/layout/default.mjs',
|
|
||||||
'shared/components/workbench/layout/cut/index.mjs',
|
|
||||||
'shared/components/workbench/layout/cut/plugin-cut-layout.mjs',
|
|
||||||
'shared/components/workbench/layout/cut/settings.mjs',
|
|
||||||
'shared/components/workbench/layout/print/index.mjs',
|
|
||||||
'shared/components/workbench/layout/print/orientation-picker.mjs',
|
|
||||||
'shared/components/workbench/layout/print/pagesize-picker.mjs',
|
|
||||||
'shared/components/workbench/layout/plugin-layout-part.mjs',
|
|
||||||
'shared/components/workbench/layout/print/settings.mjs',
|
|
||||||
'shared/components/workbench/layout/draft/buttons.mjs',
|
|
||||||
'shared/components/workbench/layout/draft/index.mjs',
|
|
||||||
'shared/components/workbench/layout/draft/stack.mjs',
|
|
||||||
'shared/components/workbench/menu/index.mjs',
|
|
||||||
'shared/components/workbench/menu/view.mjs',
|
|
||||||
'shared/components/workbench/menu/design-options/index.mjs',
|
|
||||||
'shared/components/workbench/menu/design-options/option-group.mjs',
|
|
||||||
'shared/components/workbench/menu/design-options/option-input.mjs',
|
|
||||||
'shared/components/workbench/menu/design-options/option-value.mjs',
|
|
||||||
'shared/components/workbench/menu/design-options/option.mjs',
|
|
||||||
'shared/components/workbench/menu/test-design-options/index.mjs',
|
|
||||||
'shared/components/workbench/menu/test-design-options/option.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-bool.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-list.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-mm.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-nr.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-only.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-sa-bool.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/core-setting-sa-mm.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/index.mjs',
|
|
||||||
'shared/components/workbench/menu/core-settings/setting.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/attributes.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/disable.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/index.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/list.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/log.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/path-ops.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/path.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/point.mjs',
|
|
||||||
'shared/components/workbench/menu/xray/reset.mjs',
|
|
||||||
'lab/components/about.mjs',
|
|
||||||
'lab/components/design-picker.mjs',
|
|
||||||
'lab/components/header.mjs',
|
|
||||||
'lab/components/layouts/bare.mjs',
|
|
||||||
'lab/components/layouts/lab.mjs',
|
|
||||||
'lab/components/wrappers/layout.mjs',
|
|
||||||
'lab/components/wrappers/page.mjs',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ const nl = '\n'
|
||||||
const tab = ' '
|
const tab = ' '
|
||||||
const nlt = nl + tab
|
const nlt = nl + tab
|
||||||
|
|
||||||
// Checks for node 16 or higher
|
// Checks for node 18 or higher
|
||||||
export const checkNodeVersion = () => {
|
export const checkNodeVersion = () => {
|
||||||
const node_version = process.version.slice(1).split('.')[0]
|
const node_version = process.version.slice(1).split('.')[0]
|
||||||
if (parseInt(node_version) < config.node) {
|
if (parseInt(node_version) < config.node) {
|
||||||
|
@ -47,70 +47,24 @@ export const checkNodeVersion = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper method to validate the design name
|
|
||||||
const validateDesignName = (name) => {
|
|
||||||
if (/^([a-z][a-z0-9_]*)$/.test(name)) return true
|
|
||||||
else
|
|
||||||
return ' 🙈 Please use only lowercase letters, digits, or underscores. Names must start with a lowercase letter. 🤷'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets user input to figure out what to do
|
// Gets user input to figure out what to do
|
||||||
export const getChoices = async () => {
|
export const getChoices = async () => {
|
||||||
const { template } = await prompts({
|
|
||||||
type: 'select',
|
|
||||||
name: 'template',
|
|
||||||
message: 'What template would you like to use? 📑',
|
|
||||||
choices: [
|
|
||||||
{ title: 'Tutorial', value: 'tutorial', description: 'Setup the pattern design tutorial' },
|
|
||||||
{ 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,
|
|
||||||
})
|
|
||||||
|
|
||||||
let finalName = false // we're going to use this to track whether we stay in the naming loop
|
let finalName = false // we're going to use this to track whether we stay in the naming loop
|
||||||
let overwrite = true // should we overwrite existing files?
|
let overwrite = true // should we overwrite existing files?
|
||||||
const cwd = process.cwd()
|
|
||||||
let name // name will go here
|
let name // name will go here
|
||||||
|
let sideStep // allows to do something custom
|
||||||
|
const cwd = process.cwd()
|
||||||
|
|
||||||
// while we're not finalized on a name
|
// while we're not finalized on a name
|
||||||
while (finalName === false) {
|
while (finalName === false) {
|
||||||
// request a name
|
// request a name
|
||||||
name =
|
name = (
|
||||||
template === 'tutorial' && name === undefined
|
await prompts({
|
||||||
? 'tutorial'
|
type: 'text',
|
||||||
: (
|
name: 'name',
|
||||||
await prompts({
|
message: 'Give a folder name in which we can setup the development environment? 🏷️ ',
|
||||||
type: 'text',
|
})
|
||||||
name: 'name',
|
).name
|
||||||
message: 'What name would you like the design to have? 🏷️ ([a-z0-9_] only)',
|
|
||||||
validate: validateDesignName,
|
|
||||||
})
|
|
||||||
).name
|
|
||||||
|
|
||||||
// check whether a folder with that name already exists
|
// check whether a folder with that name already exists
|
||||||
const dest = join(cwd, name)
|
const dest = join(cwd, name)
|
||||||
|
@ -127,19 +81,28 @@ export const getChoices = async () => {
|
||||||
const { nextStep } = await prompts({
|
const { nextStep } = await prompts({
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'nextStep',
|
name: 'nextStep',
|
||||||
message:
|
message: 'It looks like that folder already exists. What should we do?',
|
||||||
'It looks like you already have a design by that name in progress. What should we do?',
|
|
||||||
choices: [
|
choices: [
|
||||||
{ title: 'Rename', value: 'rename', description: 'Choose a new name for this design' },
|
{ title: 'Go back', value: 'rename', description: 'Choose a different folder name' },
|
||||||
{ title: 'Overwrite', value: 'overwrite', description: 'Overwrite the existing design' },
|
{
|
||||||
|
title: 'Overwrite',
|
||||||
|
value: 'overwrite',
|
||||||
|
description: 'Overwrite the contents in the existing folder',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Re-initialize',
|
title: 'Re-initialize',
|
||||||
value: 'reinit',
|
value: 'reinit',
|
||||||
description:
|
description:
|
||||||
"Bring in a fresh workbench, but don't overwrite existing design files (useful for updating to the latest dev environment)",
|
'Re-install depenencies, and update the development environment in this folder',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Re-download',
|
||||||
|
value: 'redownload',
|
||||||
|
description: 'Update the development environment in this folder',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
sideStep = nextStep
|
||||||
|
|
||||||
// if they said rename, we loop again. otherwise
|
// if they said rename, we loop again. otherwise
|
||||||
if (nextStep !== 'rename') {
|
if (nextStep !== 'rename') {
|
||||||
|
@ -160,7 +123,7 @@ export const getChoices = async () => {
|
||||||
initial: 0,
|
initial: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
return { template, name, manager, overwrite }
|
return { name, manager, overwrite, sideStep }
|
||||||
}
|
}
|
||||||
|
|
||||||
const capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1)
|
const capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1)
|
||||||
|
@ -209,111 +172,6 @@ const copyFileOrTemplate = async (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template the package.json
|
|
||||||
const copyPackageJson = async (config, choices) => {
|
|
||||||
const packageJsonTemplate = await readFile(
|
|
||||||
config.relativeFiles.templates['package.json'],
|
|
||||||
'utf-8'
|
|
||||||
)
|
|
||||||
|
|
||||||
await copyFileOrTemplate(packageJsonTemplate, config.dest, 'package.json', {
|
|
||||||
name: choices.name,
|
|
||||||
tag: config.tag,
|
|
||||||
dependencies: config.templateData.dependencies,
|
|
||||||
includeTests: choices.includeTests,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template the design index file
|
|
||||||
const copyIndexFile = async (config, choices) => {
|
|
||||||
// Template the index file
|
|
||||||
const indexTemplate = await readFile(config.relativeFiles.templates['index'], 'utf-8')
|
|
||||||
|
|
||||||
// get the part names based on how they are given in the configuration
|
|
||||||
const partNames = config.complexParts
|
|
||||||
? config.templateData.parts.map((p) => p.part)
|
|
||||||
: config.templateData.parts
|
|
||||||
// write the file
|
|
||||||
await copyFileOrTemplate(
|
|
||||||
indexTemplate,
|
|
||||||
config.dest,
|
|
||||||
`${designSrcDir}/index.mjs`,
|
|
||||||
{
|
|
||||||
name: choices.name,
|
|
||||||
Name: capitalize(choices.name),
|
|
||||||
parts: partNames,
|
|
||||||
},
|
|
||||||
choices.overwrite
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template the part files
|
|
||||||
const copyPartFiles = async (config, choices) => {
|
|
||||||
// Template the parts
|
|
||||||
const partTemplate = await readFile(config.relativeFiles.templates.part, 'utf-8')
|
|
||||||
// does this design inherit from another?
|
|
||||||
const doesInherit = !config.templateData.noInheritance
|
|
||||||
|
|
||||||
// all part templates need these arguments
|
|
||||||
const baseConfig = {
|
|
||||||
name: choices.name, // the name of the design
|
|
||||||
doesInherit, // whether it's an inherited design
|
|
||||||
draftUses: {}, // what parameters need to be uncommented in the draft method (default none because part is always uncommented)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it inherits, we also need the name of the design it inherits from
|
|
||||||
if (doesInherit) {
|
|
||||||
baseConfig.baseName = choices.template
|
|
||||||
baseConfig.BaseName = capitalize(choices.template)
|
|
||||||
}
|
|
||||||
|
|
||||||
// for each part
|
|
||||||
return config.templateData.parts.map((p) => {
|
|
||||||
// set up the arguments based on what's in the part's config
|
|
||||||
const templateArgs = config.complexParts
|
|
||||||
? {
|
|
||||||
...baseConfig,
|
|
||||||
...p,
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
...baseConfig,
|
|
||||||
part: p,
|
|
||||||
}
|
|
||||||
|
|
||||||
// add an uppercase version of the partName
|
|
||||||
templateArgs.Part = capitalize(templateArgs.part)
|
|
||||||
|
|
||||||
// write the part file
|
|
||||||
return copyFileOrTemplate(
|
|
||||||
partTemplate,
|
|
||||||
config.dest,
|
|
||||||
`${designSrcDir}/${templateArgs.part}.mjs`,
|
|
||||||
templateArgs,
|
|
||||||
choices.overwrite
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to copy template files
|
|
||||||
const copyAll = async (config, choices) => {
|
|
||||||
let promises = []
|
|
||||||
|
|
||||||
// Copy shared files
|
|
||||||
promises = promises.concat(
|
|
||||||
config.relativeFiles.shared.map((from) => {
|
|
||||||
if (choices.includeTests || !from.match(/e2e|playwright/))
|
|
||||||
copyFileOrTemplate(config.source.shared, config.dest, from)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
// template design files
|
|
||||||
promises.push(copyPackageJson(config, choices))
|
|
||||||
promises.push(copyIndexFile(config, choices))
|
|
||||||
promises = promises.concat(copyPartFiles(config, choices))
|
|
||||||
|
|
||||||
await Promise.all(promises)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper method to run [yarn|npm] install
|
// Helper method to run [yarn|npm] install
|
||||||
const installDependencies = async (config, choices) =>
|
const installDependencies = async (config, choices) =>
|
||||||
await execa(`${choices.manager} install`, {
|
await execa(`${choices.manager} install`, {
|
||||||
|
@ -322,22 +180,28 @@ const installDependencies = async (config, choices) =>
|
||||||
})
|
})
|
||||||
|
|
||||||
// Helper method to download web environment
|
// Helper method to download web environment
|
||||||
const downloadLabFiles = async (config) => {
|
const downloadFiles = async (config) => {
|
||||||
const promises = []
|
const promises = []
|
||||||
for (const dir in config.fetch) {
|
for (const dir in config.fetch) {
|
||||||
promises.push(
|
promises.push(
|
||||||
...config.fetch[dir].map(async (file) => {
|
...config.fetch[dir].map(async (file) => {
|
||||||
const to = typeof file === 'string' ? join(config.dest, file) : join(config.dest, file.to)
|
const to =
|
||||||
|
typeof file === 'string'
|
||||||
|
? join(config.dest, file.slice(0, 4) === 'sde/' ? file.slice(4) : file)
|
||||||
|
: join(config.dest, file.to)
|
||||||
await ensureDir(to)
|
await ensureDir(to)
|
||||||
|
const url = `${config.fileUri}/${config.repo}/${config.branch}/${dir}/${
|
||||||
|
typeof file === 'string' ? file : file.from
|
||||||
|
}`
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(
|
const res = await axios.get(url)
|
||||||
`${config.fileUri}/${config.repo}/${config.branch}/${dir}/${
|
await writeFile(
|
||||||
typeof file === 'string' ? file : file.from
|
to,
|
||||||
}`
|
typeof res.data === 'object' ? JSON.stringify(res.data, null, 2) : res.data
|
||||||
)
|
)
|
||||||
await writeFile(to, res.data)
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
if (err.response?.status === 404) console.log(`404: ${url}`)
|
||||||
|
else console.log(err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
@ -351,7 +215,7 @@ const initGitRepo = async (config, choices) => {
|
||||||
await copyFileOrTemplate(config.gitignore, config.dest, '.gitignore', {}, choices.overwrite)
|
await copyFileOrTemplate(config.gitignore, config.dest, '.gitignore', {}, choices.overwrite)
|
||||||
|
|
||||||
return execa(
|
return execa(
|
||||||
`git init -b main && git add . && git commit -m ":tada: Initialized ${choices.name} repository"`,
|
`git init -b main && git add . && git commit -m ":tada: Initialized FreeSewing stand-alone development environment"`,
|
||||||
{
|
{
|
||||||
cwd: config.dest,
|
cwd: config.dest,
|
||||||
shell: true,
|
shell: true,
|
||||||
|
@ -360,13 +224,13 @@ const initGitRepo = async (config, choices) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tips
|
// Tips
|
||||||
const showTips = (config, choices) => {
|
const showTips = (config, choices) =>
|
||||||
console.log(`
|
console.log(`
|
||||||
All done 🤓 Your new design ${chalk.yellow.bold(
|
All done 🤓 Your FreeSewing development environment was initialized in: ${chalk.green.bold(
|
||||||
choices.name
|
config.dest
|
||||||
)} was initialized in: ${chalk.green.bold(config.dest)}
|
)}
|
||||||
|
|
||||||
The code for your design is in the ${chalk.yellow.bold('design')} folder.
|
The templates for various designs are in the ${chalk.yellow.bold('design')} folder.
|
||||||
The other files and folders are the development environment. You can safely ignore those.
|
The other files and folders are the development environment. You can safely ignore those.
|
||||||
|
|
||||||
To start your development environment, follow these three steps:
|
To start your development environment, follow these three steps:
|
||||||
|
@ -377,41 +241,12 @@ const showTips = (config, choices) => {
|
||||||
)}
|
)}
|
||||||
3) Now open your browser and navigate to ${chalk.green('http://localhost:8000/')}
|
3) Now open your browser and navigate to ${chalk.green('http://localhost:8000/')}
|
||||||
|
|
||||||
${chalk.bold.yellow('🤔 More info & help')}
|
Thanks for giving FreeSewing a shot. I hope you'll 💜 it.
|
||||||
${chalk.gray('≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡')}`)
|
|
||||||
|
|
||||||
if (choices.template === 'tutorial')
|
|
||||||
console.log(`
|
|
||||||
Our pattern design tutorial is available at: ${chalk.green(
|
|
||||||
'https://freesewing.dev/tutorials/pattern-design'
|
|
||||||
)}
|
|
||||||
|
|
||||||
It will walk your through the process step by step.
|
|
||||||
If you get stuck, reach out to our community on Discord: ${chalk.green(
|
|
||||||
'https://discord.freesewing.dev/'
|
|
||||||
)}
|
|
||||||
The ${chalk.bold('development-help')} channel is a good place to ask questions
|
|
||||||
|
|
||||||
Don't be shy to reach out. If something is not clear, that's on us, not on you.
|
|
||||||
So your feedback really helps us improve our tutorial/documentation.
|
|
||||||
|
|
||||||
Thanks for giving FreeSewing a shot. We hope you'll 💜 it.
|
|
||||||
|
|
||||||
Have fun 🤓
|
Have fun 🤓
|
||||||
`)
|
|
||||||
else
|
|
||||||
console.log(`
|
|
||||||
|
|
||||||
FreeSewing's documentation for developers is available at: ${chalk.green(
|
joost
|
||||||
'https://freesewing.dev/'
|
`)
|
||||||
)}
|
|
||||||
|
|
||||||
Our community is on Discord: ${chalk.green('https://discord.freesewing.dev/')}
|
|
||||||
The ${chalk.bold('development-help')} channel is a good place to ask for help if you get stuck
|
|
||||||
|
|
||||||
Happy hacking 🤓
|
|
||||||
`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates the environment based on the user's choices
|
// Creates the environment based on the user's choices
|
||||||
export const createEnvironment = async (choices) => {
|
export const createEnvironment = async (choices) => {
|
||||||
|
@ -423,87 +258,60 @@ export const createEnvironment = async (choices) => {
|
||||||
shared: join(newDesignDir, `shared`),
|
shared: join(newDesignDir, `shared`),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create target directory
|
|
||||||
await mkdir(config.dest, { recursive: true })
|
|
||||||
|
|
||||||
// get the template files in a dictionary
|
|
||||||
const templates = {}
|
|
||||||
const templateFiles = await rdir(config.source.templates)
|
|
||||||
templateFiles.forEach((file) => {
|
|
||||||
const relativeName = relative(config.source.templates, file).replace(/(\.mjs)*\.mustache/, '')
|
|
||||||
templates[relativeName] = file
|
|
||||||
})
|
|
||||||
|
|
||||||
config.relativeFiles = {
|
|
||||||
templates,
|
|
||||||
shared: (await rdir(config.source.shared)).map((file) => relative(config.source.shared, file)),
|
|
||||||
}
|
|
||||||
|
|
||||||
config.templateData = await import(pathToFileURL(config.source.templateData))
|
|
||||||
// does this base have parts with a lot of attending config?
|
|
||||||
config.complexParts = typeof config.templateData.parts[0] === 'object'
|
|
||||||
|
|
||||||
// Output a linebreak
|
// Output a linebreak
|
||||||
console.log()
|
console.log()
|
||||||
|
|
||||||
// Copy/Template files
|
// Download files from GitHub
|
||||||
try {
|
try {
|
||||||
await oraPromise(copyAll(config, choices), {
|
await oraPromise(downloadFiles(config), {
|
||||||
text:
|
text:
|
||||||
chalk.white.bold('🟨⬜⬜⬜ Copying template files') +
|
chalk.white.bold('🟧⬜⬜ Downloading components from GitHub') +
|
||||||
chalk.white.dim(' | Just a moment'),
|
|
||||||
successText: chalk.white.bold('🟩⬜⬜⬜ Copied template files'),
|
|
||||||
failText: chalk.white.bold(
|
|
||||||
'🟥⬜⬜⬜ Failed to copy template files | Development environment will not function'
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install dependencies
|
|
||||||
try {
|
|
||||||
await oraPromise(installDependencies(config, choices), {
|
|
||||||
text:
|
|
||||||
chalk.white.bold('🟩🟨⬜⬜ Installing dependencies') +
|
|
||||||
chalk.white.dim(' | Please wait, this will take a while'),
|
|
||||||
successText: chalk.white.bold('🟩🟩⬜⬜ Installed dependencies'),
|
|
||||||
failText: chalk.white.bold(
|
|
||||||
'🟩🟥⬜⬜ Failed to install dependencies | Development environment will not function'
|
|
||||||
),
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
/* no feedback here */
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch web components
|
|
||||||
try {
|
|
||||||
await oraPromise(downloadLabFiles(config), {
|
|
||||||
text:
|
|
||||||
chalk.white.bold('🟩🟩🟨⬜ Downloading web components') +
|
|
||||||
chalk.white.dim(' | Almost there'),
|
chalk.white.dim(' | Almost there'),
|
||||||
successText: chalk.white.bold('🟩🟩🟩⬜ Downloaded web components'),
|
successText: chalk.white.bold('🟩⬜⬜ Downloaded components from GitHub'),
|
||||||
failText: chalk.white.bold(
|
failText: chalk.white.bold(
|
||||||
'🟩🟩🟥⬜ Failed to download web components | Development environment will not function'
|
'🟥⬜⬜ Failed to download components from GitHub | The development environment will not function'
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
/* no feedback here */
|
/* no feedback here */
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize git repository
|
if (!choices.sideStep) {
|
||||||
try {
|
// Create target directory
|
||||||
await oraPromise(initGitRepo(config, choices), {
|
await mkdir(config.dest, { recursive: true })
|
||||||
text:
|
|
||||||
chalk.white.bold('🟩🟩🟩⬜ Initializing git repository') +
|
// Install dependencies
|
||||||
chalk.white.dim(' | You have git, right?'),
|
try {
|
||||||
successText: chalk.white.bold('🟩🟩🟩🟩 Initialized git repository'),
|
await oraPromise(installDependencies(config, choices), {
|
||||||
failText:
|
text:
|
||||||
chalk.white.bold('🟩🟩🟩🟥 Failed to initialize git repository') +
|
chalk.white.bold('🟩🟧⬜ Installing dependencies') +
|
||||||
chalk.white.dim(' | This does not stop you from developing your design'),
|
chalk.white.dim(' | Please wait, this will take a while'),
|
||||||
})
|
successText: chalk.white.bold('🟩🟩⬜ Installed dependencies'),
|
||||||
} catch (err) {
|
failText: chalk.white.bold(
|
||||||
console.log(err)
|
'🟩🟥⬜ Failed to install dependencies | The development environment will not function'
|
||||||
|
),
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
/* no feedback here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!choices.sideStep) {
|
||||||
|
// Initialize git repository
|
||||||
|
try {
|
||||||
|
await oraPromise(initGitRepo(config, choices), {
|
||||||
|
text:
|
||||||
|
chalk.white.bold('🟩🟩🟧 Initializing git repository') +
|
||||||
|
chalk.white.dim(' | You have git, right?'),
|
||||||
|
successText: chalk.white.bold('🟩🟩🟩 Initialized git repository'),
|
||||||
|
failText:
|
||||||
|
chalk.white.bold('🟩🟩🟥 Failed to initialize git repository') +
|
||||||
|
chalk.white.dim(' | This does not stop the development environment from functioning'),
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// All done. Show tips
|
// All done. Show tips
|
||||||
|
|
|
@ -2,16 +2,25 @@ import rdir from 'recursive-readdir'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
|
||||||
const ignore = [
|
const ignore = [
|
||||||
'package.json',
|
|
||||||
'node_modules',
|
'node_modules',
|
||||||
'.eslint',
|
'.eslint',
|
||||||
'.gitignore',
|
'.gitignore',
|
||||||
'.md',
|
'.md',
|
||||||
'lab/components/header.js',
|
'.next',
|
||||||
'lab/components/help-us.js',
|
'prebuild.mjs',
|
||||||
'lab/components/search.js',
|
'prebuild',
|
||||||
'lab/components/footer.js',
|
'public/locales',
|
||||||
'shared/config/measurements.js',
|
'shared/config/measurements.js',
|
||||||
|
'sde/public/android-chrome-192x192.png',
|
||||||
|
'sde/public/android-chrome-384x384.png',
|
||||||
|
'sde/public/apple-touch-icon.png',
|
||||||
|
'sde/public/browserconfig.xml',
|
||||||
|
'sde/public/favicon-16x16.png',
|
||||||
|
'sde/public/favicon-32x32.png',
|
||||||
|
'sde/public/favicon.ico',
|
||||||
|
'sde/public/mstile-150x150.png',
|
||||||
|
'sde/public/safari-pinned-tab.svg',
|
||||||
|
'sde/public/site.webmanifest',
|
||||||
]
|
]
|
||||||
|
|
||||||
const getFiles = async (dir) => {
|
const getFiles = async (dir) => {
|
||||||
|
@ -28,9 +37,9 @@ const getFiles = async (dir) => {
|
||||||
|
|
||||||
const doIt = async () => {
|
const doIt = async () => {
|
||||||
let files = []
|
let files = []
|
||||||
const shared = await getFiles('../../sites/shared')
|
const sde = await getFiles('../../sites/sde')
|
||||||
const lab = await getFiles('../../sites/lab/components')
|
const shared = await getFiles('../../sites/shared/config')
|
||||||
console.log(JSON.stringify([...shared, ...lab], null, 2))
|
console.log(JSON.stringify([...shared, ...sde], null, 2))
|
||||||
}
|
}
|
||||||
|
|
||||||
doIt()
|
doIt()
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { test, expect } from '@playwright/test'
|
|
||||||
|
|
||||||
test('Compiles and drafts', async ({ page }) => {
|
|
||||||
await page.goto('http://localhost:8000/design')
|
|
||||||
|
|
||||||
await page.waitForSelector('main')
|
|
||||||
if (await page.getByRole('heading', { name: 'Preload a set of measurements' }).isVisible()) {
|
|
||||||
await page
|
|
||||||
.getByRole('list')
|
|
||||||
.filter({ hasText: 'Size 28Size 30Size 32Size 34Size 36Size 38Size 40Size 42Size 44Size 46' })
|
|
||||||
.getByRole('button', { name: 'Size 36' })
|
|
||||||
.click()
|
|
||||||
await page.getByTitle('draftDesign').click()
|
|
||||||
}
|
|
||||||
|
|
||||||
await expect(page.getByText('Something went wrong')).toHaveCount(0)
|
|
||||||
await expect(page.getByText('Unhandled Runtime Error')).toHaveCount(0)
|
|
||||||
await expect(page.getByTitle('Measurements')).toBeVisible()
|
|
||||||
})
|
|
|
@ -1,145 +0,0 @@
|
||||||
// Hooks
|
|
||||||
import { useTranslation } from 'next-i18next'
|
|
||||||
// Components
|
|
||||||
import Link from 'next/link'
|
|
||||||
import { FreeSewingLogo } from 'shared/components/logos/freesewing.mjs'
|
|
||||||
import { OsiLogo } from 'shared/components/logos/osi.mjs'
|
|
||||||
import { CCLogo } from 'shared/components/logos/cc.mjs'
|
|
||||||
import { CCByLogo } from 'shared/components/logos/cc-by.mjs'
|
|
||||||
import { Ribbon } from 'shared/components/ribbon.mjs'
|
|
||||||
import { WordMark } from 'shared/components/wordmark.mjs'
|
|
||||||
import {
|
|
||||||
DiscordIcon,
|
|
||||||
FacebookIcon,
|
|
||||||
GithubIcon,
|
|
||||||
InstagramIcon,
|
|
||||||
RedditIcon,
|
|
||||||
TwitterIcon,
|
|
||||||
} from 'shared/components/icons.mjs'
|
|
||||||
|
|
||||||
// Classes
|
|
||||||
const link = 'text-secondary font-bold hover:pointer hover:underline px-1'
|
|
||||||
const accent = 'text-accent font-bold text-lg px-1 block sm:inline'
|
|
||||||
const freesewing = 'px-1 text-lg font-bold block sm:inline'
|
|
||||||
|
|
||||||
// Keep these translations in the component because they're only used here
|
|
||||||
const translations = {
|
|
||||||
cc: (
|
|
||||||
<span>
|
|
||||||
Content on FreeSewing.org is available under{' '}
|
|
||||||
<a className={link} href="https://creativecommons.org/licenses/by/4.0/">
|
|
||||||
a Creative Commons license
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
mit: (
|
|
||||||
<span>
|
|
||||||
The FreeSewing source code is{' '}
|
|
||||||
<a href="https://github.com/freesewing/freesewing" className={link}>
|
|
||||||
available on Github
|
|
||||||
</a>{' '}
|
|
||||||
under{' '}
|
|
||||||
<a href="https://opensource.org/licenses/MIT" className={link}>
|
|
||||||
the MIT license
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
sponsors: (
|
|
||||||
<>
|
|
||||||
<span className={freesewing}>FreeSewing</span> is sponsored by these{' '}
|
|
||||||
<span className={accent}>awesome companies</span>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
const icon = { className: 'w-8 lg:w-12 h-8 lg:h-12' }
|
|
||||||
const social = {
|
|
||||||
Discord: {
|
|
||||||
icon: <DiscordIcon {...icon} />,
|
|
||||||
href: 'https://discord.freesewing.org/',
|
|
||||||
},
|
|
||||||
Instagram: {
|
|
||||||
icon: <InstagramIcon {...icon} />,
|
|
||||||
href: 'https://instagram.com/freesewing_org',
|
|
||||||
},
|
|
||||||
Facebook: {
|
|
||||||
icon: <FacebookIcon {...icon} />,
|
|
||||||
href: 'https://www.facebook.com/groups/627769821272714/',
|
|
||||||
},
|
|
||||||
Github: {
|
|
||||||
icon: <GithubIcon {...icon} />,
|
|
||||||
href: 'https://github.com/freesewing',
|
|
||||||
},
|
|
||||||
Reddit: {
|
|
||||||
icon: <RedditIcon {...icon} />,
|
|
||||||
href: 'https://www.reddit.com/r/freesewing/',
|
|
||||||
},
|
|
||||||
Twitter: {
|
|
||||||
icon: <TwitterIcon {...icon} />,
|
|
||||||
href: 'https://twitter.com/freesewing_org',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Footer = ({ app }) => {
|
|
||||||
const { t } = useTranslation(['common', 'patrons'])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<footer className="bg-neutral">
|
|
||||||
<Ribbon loading={app.loading} theme={app.theme} />
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-4 py-12 2xl:py-20 text-neutral-content px-4">
|
|
||||||
{/* First col - CC & MIT */}
|
|
||||||
<div className="mb-20 order-1 mt-20 2xl:mt-0 2xl:mb-0">
|
|
||||||
<div className="max-w-md m-auto">
|
|
||||||
<div>
|
|
||||||
<CCLogo className="w-64 m-auto" />
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row gap-2 justify-center items-center mt-8">
|
|
||||||
<CCByLogo className="w-8 lg:w-12" />
|
|
||||||
<p className="text-neutral-content text-right basis-4/5 lg:basis-3/4 leading-5">
|
|
||||||
{translations.cc}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row gap-2 justify-center items-center mt-4">
|
|
||||||
<OsiLogo className="w-8 lg:w-12" />
|
|
||||||
<p className="text-neutral-content text-right basis-4/5 lg:basis-3/4 leading-5">
|
|
||||||
{translations.mit}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Second col - Social & Sponsors */}
|
|
||||||
<div className="lg:col-span-2 -order-2 2xl:order-2 px-4 lg:px-0">
|
|
||||||
{/* Social icons */}
|
|
||||||
<div className="w-full sm:w-auto flex flex-row flex-wrap gap-4 lg:gap-8 items-center justify-center">
|
|
||||||
{Object.keys(social).map((item) => (
|
|
||||||
<Link
|
|
||||||
key={item}
|
|
||||||
href={social[item].href}
|
|
||||||
className="hover:text-secondary hover:-mt-2 transition-all"
|
|
||||||
title={item}
|
|
||||||
>
|
|
||||||
{social[item].icon}
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Col 3 - Logo & Slogan */}
|
|
||||||
<div className="w-full 4xl:w-auto xl:max-w-md mb-8 text-center order-3 mt-0 lg:mt-20 2xl:mt-0 2xl:mb-0">
|
|
||||||
<div className="max-w-md m-auto">
|
|
||||||
<FreeSewingLogo stroke="none" size={164} className="w-40 lg:w-64 m-auto m-auto" />
|
|
||||||
<h5 className="lg:text-3xl mt-4">
|
|
||||||
<WordMark />
|
|
||||||
</h5>
|
|
||||||
<p className="bold text-neutral-content text-normal lg:text-xl leading-5">
|
|
||||||
{t('sloganCome')}
|
|
||||||
<br />
|
|
||||||
{t('sloganStay')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,82 +0,0 @@
|
||||||
import { useState, useEffect } from 'react'
|
|
||||||
import Link from 'next/link'
|
|
||||||
import { ModalThemePicker } from 'shared/components/modal/theme-picker.mjs'
|
|
||||||
import { ModalLocalePicker } from 'shared/components/modal/locale-picker.mjs'
|
|
||||||
import { CloseIcon, MenuIcon, HelpIcon, DocsIcon } from 'shared/components/icons/close.js'
|
|
||||||
import { Ribbon } from 'shared/components/ribbon.js'
|
|
||||||
import { WordMark } from 'shared/components/wordmark.js'
|
|
||||||
import { useTranslation } from 'next-i18next'
|
|
||||||
|
|
||||||
const btnClasses =
|
|
||||||
'btn btn-ghost text-base font-medium btn-sm text-neutral-content ' +
|
|
||||||
' capitalize hover:bg-transparent hover:text-secondary-focus'
|
|
||||||
|
|
||||||
export 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 (
|
|
||||||
<header
|
|
||||||
className={`
|
|
||||||
fixed top-0 left-0
|
|
||||||
bg-neutral
|
|
||||||
w-full
|
|
||||||
z-30
|
|
||||||
transition-transform
|
|
||||||
${show ? '' : 'fixed top-0 left-0 -translate-y-20'}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<div className="p-2 flex flex-row justify-between text-neutral-content">
|
|
||||||
<div className="flex flex-row items-center">
|
|
||||||
<button
|
|
||||||
className={`
|
|
||||||
btn btn-sm btn-ghost
|
|
||||||
text-neutral-content bg-transparent
|
|
||||||
hover:text-secondary-focus
|
|
||||||
lg:hidden
|
|
||||||
`}
|
|
||||||
onClick={app.togglePrimaryMenu}
|
|
||||||
>
|
|
||||||
{app.primaryMenu ? <CloseIcon /> : <MenuIcon />}
|
|
||||||
</button>
|
|
||||||
<WordMark />
|
|
||||||
<div className="hidden md:flex flex-row items-center">
|
|
||||||
<a role="button" className={btnClasses} href="https://freesewing.dev/">
|
|
||||||
<DocsIcon />
|
|
||||||
<span className="ml-2">{t('docs')}</span>
|
|
||||||
</a>
|
|
||||||
<Link href="/support" role="button" className={btnClasses}>
|
|
||||||
<>
|
|
||||||
<HelpIcon />
|
|
||||||
<span className="ml-2">{t('support')}</span>
|
|
||||||
</>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="hidden md:flex flex-row items-center gap-2">
|
|
||||||
<ModalThemePicker app={app} />
|
|
||||||
<ModalLocalePicker app={app} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Ribbon loading={app.loading} theme={app.theme} />
|
|
||||||
</header>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
|
|
||||||
import { BeforeNav } from './lab'
|
|
||||||
|
|
||||||
export const DefaultLayout = ({ app, children = [] }) => {
|
|
||||||
const router = useRouter()
|
|
||||||
const slug = router.asPath.slice(1)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AsideNavigation app={app} slug={slug} before={<BeforeNav app={app} />} mobileOnly />
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import { AsideNavigation } from 'shared/components/navigation/aside.mjs'
|
|
||||||
|
|
||||||
export const HomeLayout = ({ app, title = false, children = [] }) => (
|
|
||||||
<div className="max-w-7xl m-auto mt-32">
|
|
||||||
{title && <h1 className="capitalize">{title}</h1>}
|
|
||||||
<AsideNavigation app={app} mobileOnly />
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
)
|
|
|
@ -1,44 +0,0 @@
|
||||||
import { ModalThemePicker } from 'shared/components/modal/theme-picker.mjs'
|
|
||||||
import { ModalLocalePicker } from 'shared/components/modal/locale-picker.mjs'
|
|
||||||
|
|
||||||
export const BeforeNav = ({ app }) => (
|
|
||||||
<>
|
|
||||||
<div className="md:hidden flex flex-row flex-wrap sm:flex-nowrap gap-2 mb-2">
|
|
||||||
<ModalThemePicker app={app} />
|
|
||||||
<ModalLocalePicker app={app} />
|
|
||||||
</div>
|
|
||||||
<div className="md:hidden flex flex-row flex-wrap sm:flex-nowrap gap-2 mb-2"></div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
export const LabLayout = ({ app, AltMenu, children = [] }) => (
|
|
||||||
<div className="py-24 lg:py-36 flex flex-row">
|
|
||||||
<div className="w-full px-8">{children}</div>
|
|
||||||
<aside
|
|
||||||
className={`
|
|
||||||
fixed top-0 right-0
|
|
||||||
pt-20 pb-8 px-8
|
|
||||||
md:pt-0
|
|
||||||
md:relative md:transform-none
|
|
||||||
h-screen w-screen
|
|
||||||
bg-base-100
|
|
||||||
md:bg-base-50
|
|
||||||
md:flex
|
|
||||||
md:sticky
|
|
||||||
overflow-y-scroll
|
|
||||||
z-20
|
|
||||||
bg-base-100 text-base-content
|
|
||||||
transition-all
|
|
||||||
xl:w-1/4
|
|
||||||
${app.primaryMenu ? '' : 'translate-x-[-100%]'} transition-transform
|
|
||||||
md:flex-row
|
|
||||||
md:w-80
|
|
||||||
lg:w-96
|
|
||||||
shrink-0
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
<BeforeNav app={app} />
|
|
||||||
{AltMenu}
|
|
||||||
</aside>
|
|
||||||
</div>
|
|
||||||
)
|
|
|
@ -1,4 +0,0 @@
|
||||||
// Noop placeholder
|
|
||||||
const Noop = () => null
|
|
||||||
|
|
||||||
export default Noop
|
|
|
@ -1,56 +0,0 @@
|
||||||
import { useState } from 'react'
|
|
||||||
// Locale and translation
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { useTheme } from 'shared/hooks/useTheme.mjs'
|
|
||||||
|
|
||||||
export const useApp = () => {
|
|
||||||
// Load translation method
|
|
||||||
const locale = useRouter().locale
|
|
||||||
|
|
||||||
// Persistent state
|
|
||||||
const [theme, setTheme] = useTheme()
|
|
||||||
|
|
||||||
// React State
|
|
||||||
const [primaryMenu, setPrimaryMenu] = useState(false)
|
|
||||||
const [navigation, setNavigation] = useState({})
|
|
||||||
const [slug, setSlug] = useState('/')
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
|
|
||||||
// State methods
|
|
||||||
const togglePrimaryMenu = () => setPrimaryMenu(!primaryMenu)
|
|
||||||
|
|
||||||
return {
|
|
||||||
// Static vars
|
|
||||||
site: 'lab',
|
|
||||||
|
|
||||||
// i18n
|
|
||||||
locale,
|
|
||||||
|
|
||||||
// State
|
|
||||||
loading,
|
|
||||||
navigation,
|
|
||||||
primaryMenu,
|
|
||||||
slug,
|
|
||||||
theme,
|
|
||||||
|
|
||||||
// State setters
|
|
||||||
setLoading,
|
|
||||||
setNavigation,
|
|
||||||
setPrimaryMenu,
|
|
||||||
setSlug,
|
|
||||||
setTheme,
|
|
||||||
startLoading: () => {
|
|
||||||
setLoading(true)
|
|
||||||
setPrimaryMenu(false)
|
|
||||||
}, // Always close menu when navigating
|
|
||||||
stopLoading: () => setLoading(false),
|
|
||||||
|
|
||||||
// State handlers
|
|
||||||
togglePrimaryMenu,
|
|
||||||
|
|
||||||
// Standalone is for the development environment
|
|
||||||
standalone: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default useApp
|
|
|
@ -1,13 +0,0 @@
|
||||||
// See: https://github.com/isaachinman/next-i18next
|
|
||||||
module.exports = {
|
|
||||||
i18n: {
|
|
||||||
defaultLocale: 'en',
|
|
||||||
locales: ['en', 'de', 'es', 'fr', 'nl'],
|
|
||||||
defaultNS: 'common',
|
|
||||||
},
|
|
||||||
interpolation: {
|
|
||||||
prefix: '{',
|
|
||||||
suffix: '}',
|
|
||||||
},
|
|
||||||
localeStructure: '{lng}/{ns}',
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
import path from 'path'
|
|
||||||
import i18nConfig from './next-i18next.config.js'
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
i18n: i18nConfig.i18n,
|
|
||||||
pageExtensions: ['mjs'],
|
|
||||||
webpack: (config, options) => {
|
|
||||||
// Aliases
|
|
||||||
config.resolve.alias.shared = path.resolve('./shared/')
|
|
||||||
config.resolve.alias.site = path.resolve('./lab/')
|
|
||||||
config.resolve.alias.design = path.resolve('./design/')
|
|
||||||
|
|
||||||
return config
|
|
||||||
},
|
|
||||||
}
|
|
||||||
export default config
|
|
|
@ -1,6 +0,0 @@
|
||||||
import 'shared/styles/globals.css'
|
|
||||||
import { appWithTranslation } from 'next-i18next'
|
|
||||||
|
|
||||||
const FreeSewingLab = ({ Component, pageProps }) => <Component {...pageProps} />
|
|
||||||
|
|
||||||
export default appWithTranslation(FreeSewingLab)
|
|
|
@ -1,26 +0,0 @@
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
|
||||||
import { Pattern } from 'design/src/index.mjs'
|
|
||||||
import { useApp } from 'site/hooks/useApp.mjs'
|
|
||||||
import { PageWrapper } from 'site/components/wrappers/page.mjs'
|
|
||||||
import { LabLayout } from 'site/components/layouts/lab.mjs'
|
|
||||||
import { WorkbenchWrapper } from 'shared/components/wrappers/workbench.mjs'
|
|
||||||
|
|
||||||
const WorkbenchPage = () => {
|
|
||||||
const app = useApp()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageWrapper app={app}>
|
|
||||||
<WorkbenchWrapper {...{ app, design: Pattern, layout: LabLayout }} />
|
|
||||||
</PageWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default WorkbenchPage
|
|
||||||
|
|
||||||
export async function getStaticProps({ locale }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
...(await serverSideTranslations(locale)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
|
||||||
import { useTranslation } from 'next-i18next'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import Link from 'next/link'
|
|
||||||
import { PageWrapper } from 'site/components/wrappers/page.mjs'
|
|
||||||
import { useApp } from 'site/hooks/useApp.mjs'
|
|
||||||
import { HomeLayout } from 'site/components/layouts/home.mjs'
|
|
||||||
import { FreeSewingIcon } from 'shared/components/icons.mjs'
|
|
||||||
import { Popout } from 'shared/components/popout.mjs'
|
|
||||||
import themes from 'shared/themes/index.js'
|
|
||||||
|
|
||||||
const translations = {
|
|
||||||
sade: {
|
|
||||||
en: `Stand-alone development environment`,
|
|
||||||
nl: `Vrijstaande ontwikkeling omgeving`,
|
|
||||||
},
|
|
||||||
load: {
|
|
||||||
en: `To your design`,
|
|
||||||
nl: `Naar jouw ontwerp`,
|
|
||||||
},
|
|
||||||
tips: {
|
|
||||||
en: (
|
|
||||||
<Popout tip compact>
|
|
||||||
Edit the files in the <strong>design</strong> folder, and we'll auto-update your design
|
|
||||||
</Popout>
|
|
||||||
),
|
|
||||||
nl: (
|
|
||||||
<Popout tip compact>
|
|
||||||
Bewerk de bestanden in de <strong>design</strong> map, en we passen je ontwerp automatisch
|
|
||||||
aan
|
|
||||||
</Popout>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const HomePage = () => {
|
|
||||||
const app = useApp()
|
|
||||||
const router = useRouter()
|
|
||||||
const { t } = useTranslation(['common', 'patrons', 'locales', 'themes'])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageWrapper app={app} title={false} layout={HomeLayout}>
|
|
||||||
<div className="text-center w-full pt-20 pb-10 max-w-4xl m-auto">
|
|
||||||
<FreeSewingIcon className="w-96 m-auto" />
|
|
||||||
<h1>FreeSewing</h1>
|
|
||||||
<h4>{translations.sade[app.locale]}</h4>
|
|
||||||
<Link href="/design" className="btn btn-primary btn-lg h-20 my-8 mb-12">
|
|
||||||
<>
|
|
||||||
<span role="image" className="text-4xl px-6">
|
|
||||||
👉
|
|
||||||
</span>
|
|
||||||
<span className="text-xl px-2">{translations.load[app.locale]}</span>
|
|
||||||
<span role="image" className="text-4xl px-6">
|
|
||||||
👈
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
</Link>
|
|
||||||
{translations.tips[app.locale]}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row flex-wrap gap-4 w-full max-w-4xl m-auto justify-center">
|
|
||||||
{router.locales.map((locale) => (
|
|
||||||
<Link
|
|
||||||
href={router.asPath}
|
|
||||||
locale={locale}
|
|
||||||
key={locale}
|
|
||||||
className="btn btn-ghost text-base-content hover:bg-base-200"
|
|
||||||
>
|
|
||||||
<span className="text-base-content">{t(`locales:${locale}`)}</span>
|
|
||||||
</Link>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-row flex-wrap gap-4 w-full max-w-4xl m-auto justify-center mt-4">
|
|
||||||
{Object.keys(themes).map((theme) => (
|
|
||||||
<button
|
|
||||||
key={theme}
|
|
||||||
onClick={() => app.setTheme(theme)}
|
|
||||||
className="btn btn-ghost hover:bg-base-200"
|
|
||||||
>
|
|
||||||
<span className="text-base-content">{t(`themes:${theme}Theme`)}</span>
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="py-20">
|
|
||||||
<h2>{t('patrons:supportFreesewing')}</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<div>
|
|
||||||
<p className="max-w-3xl">{t('patrons:patronLead')}</p>
|
|
||||||
<p className="max-w-3xl">{t('patrons:patronPitch')}</p>
|
|
||||||
</div>
|
|
||||||
<a className="btn btn-accent btn-lg ">
|
|
||||||
<span role="image" className="text-4xl px-4">
|
|
||||||
🥰
|
|
||||||
</span>
|
|
||||||
<span className="px-2">{t('patrons:becomeAPatron')}</span>
|
|
||||||
<span role="image" className="text-4xl px-4">
|
|
||||||
🙏🏻
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* here to force Tailwind inclusion of the w-8 h-8 classes */}
|
|
||||||
<span className="w-8 h-8" />
|
|
||||||
</PageWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HomePage
|
|
||||||
|
|
||||||
export async function getStaticProps({ locale }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
...(await serverSideTranslations(locale)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,127 +0,0 @@
|
||||||
import { useTranslation } from 'next-i18next'
|
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
|
||||||
import { PageWrapper } from 'site/components/wrappers/page.mjs'
|
|
||||||
import { useApp } from 'site/hooks/useApp.mjs'
|
|
||||||
import { DefaultLayout } from 'site/components/layouts/default.mjs'
|
|
||||||
import { DiscordIcon, GithubIcon, CcIcon, HeartIcon, DocsIcon } from 'shared/components/icons/docs'
|
|
||||||
|
|
||||||
const gh = `<a class="text-secondary hover:text-secondary-focus"
|
|
||||||
href="https://github.com/freesewing/freesewing">freesewing/freesewing</a>`
|
|
||||||
const fsd = `<a class="text-secondary hover:text-secondary-focus"
|
|
||||||
href="https://freesewing.dev">freesewing.dev</a>`
|
|
||||||
|
|
||||||
const translations = {
|
|
||||||
discord: {
|
|
||||||
en: `Our Discord server on is the best place to ask questions, or hang
|
|
||||||
out with other members of the FreeSewing community.`,
|
|
||||||
nl: `Onze Discord server is de best plek om vragen te stellen, hulp te ontvangen,
|
|
||||||
of gewoon een leuke tijd te spenderen met andere leden van de FreeSewing gemeenschap.`,
|
|
||||||
},
|
|
||||||
github: {
|
|
||||||
en: `For bug reports, please create an issue in the ${gh} repository on Github.
|
|
||||||
This is also where you'll find all our source code.`,
|
|
||||||
nl: `Een bug gevonden? Maak dan een issue aan in de ${gh} repository op Github.
|
|
||||||
Dit is ook waar je al de FreeSewing broncode kan vinden.`,
|
|
||||||
},
|
|
||||||
cc: {
|
|
||||||
en: `Every two weeks, there's the FreeSewing contributor call, which is when we discuss
|
|
||||||
ongoing issues, future plans, and news big and small about FreeSewing and its community.`,
|
|
||||||
nl: `Elke twee weken is er de FreeSewing contributor call (Engelstalig), waar de FreeSewing
|
|
||||||
vrijwilligers de lopende zaken bespreken. Ook de plannen voor de toekomst en groot en klein
|
|
||||||
nieuws over FreeSewing en de gemeenschap komen aan bod.`,
|
|
||||||
},
|
|
||||||
docs: {
|
|
||||||
en: `Our documentation for developers hosted on ${fsd}. You can find guides and how-to's
|
|
||||||
there, as well as reference documantation for FreeSewing's core API.
|
|
||||||
<br /> <br />
|
|
||||||
We stive to provide excellent documentation. So if something is not clear please, let us know.`,
|
|
||||||
nl: `Onze documentatie voor ontwikkelaars is beschikbaar op ${fsd}. Je vindt er guides en how-to's,
|
|
||||||
alsook de referentie documentatie voor FreeSewing's core API.
|
|
||||||
<br /> <br />
|
|
||||||
We streven ernaar om uitstekende documentatie te voorzien. Dus als er iets niet duidelijk is, laat
|
|
||||||
het ons dan zeker weten.`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
const SupportPage = () => {
|
|
||||||
const app = useApp()
|
|
||||||
const { t } = useTranslation(['common', 'patrons'])
|
|
||||||
return (
|
|
||||||
<PageWrapper app={app} title={t('support')} layout={DefaultLayout}>
|
|
||||||
<h2 className="border-0">Discord</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<p className="max-w-3xl">{translations.discord[app.locale]}</p>
|
|
||||||
<a className="btn btn-primary btn-lg w-96" href="https://discord.freesewing.org/">
|
|
||||||
<DiscordIcon />
|
|
||||||
<span className="ml-4">discord.freesewing.org</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="border-0">Github</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<p
|
|
||||||
className="max-w-3xl"
|
|
||||||
dangerouslySetInnerHTML={{ __html: translations.github[app.locale] }}
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
className="btn btn-primary btn-outline btn-lg w-96"
|
|
||||||
href="https://github.com/freesewing/freesewing"
|
|
||||||
>
|
|
||||||
<GithubIcon />
|
|
||||||
<span className="ml-4">github.com/freesewing</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="border-0">{t('docs')}</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<p
|
|
||||||
className="max-w-3xl"
|
|
||||||
dangerouslySetInnerHTML={{ __html: translations.docs[app.locale] }}
|
|
||||||
/>
|
|
||||||
<a className="btn btn-primary btn-outline btn-lg w-96" href="https://freesewing.dev/">
|
|
||||||
<DocsIcon />
|
|
||||||
<span className="ml-4">www.FreeSewing.dev</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 className="border-0">Contributor Calls</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<p
|
|
||||||
className="max-w-3xl"
|
|
||||||
dangerouslySetInnerHTML={{ __html: translations.cc[app.locale] }}
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
className="btn btn-primary btn-outline btn-lg w-96"
|
|
||||||
href="https://github.com/freesewing/freesewing/discussions?discussions_q=label%3A%22%3Atv%3A+fscc%22"
|
|
||||||
>
|
|
||||||
<CcIcon />
|
|
||||||
<span className="ml-4">Contributor Calls</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="py-20">
|
|
||||||
<h2 className="border-0">{t('patrons:supportFreesewing')}</h2>
|
|
||||||
<div className="flex flex-row flex-wrap gap-2">
|
|
||||||
<div>
|
|
||||||
<p className="max-w-3xl">{t('patrons:patronLead')}</p>
|
|
||||||
<p className="max-w-3xl">{t('patrons:patronPitch')}</p>
|
|
||||||
</div>
|
|
||||||
<a className="btn btn-accent btn-lg w-96">
|
|
||||||
<HeartIcon className="fill-accent-content stroke-accent-content w-6 h-6" />
|
|
||||||
<span className="ml-4">{t('patrons:becomeAPatron')}</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</PageWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SupportPage
|
|
||||||
|
|
||||||
export async function getStaticProps({ locale }) {
|
|
||||||
return {
|
|
||||||
props: {
|
|
||||||
...(await serverSideTranslations(locale)),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
const { defineConfig, devices } = require('@playwright/test')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see https://playwright.dev/docs/test-configuration
|
|
||||||
*/
|
|
||||||
module.exports = defineConfig({
|
|
||||||
testDir: './e2e',
|
|
||||||
/* Run tests in files in parallel */
|
|
||||||
fullyParallel: true,
|
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
||||||
forbidOnly: !!process.env.CI,
|
|
||||||
/* Retry on CI only */
|
|
||||||
retries: process.env.CI ? 2 : 0,
|
|
||||||
/* Opt out of parallel tests on CI. */
|
|
||||||
workers: process.env.CI ? 1 : undefined,
|
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
||||||
reporter: 'html',
|
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
||||||
use: {
|
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
||||||
// baseURL: 'http://127.0.0.1:3000',
|
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
||||||
trace: 'on-first-retry',
|
|
||||||
},
|
|
||||||
|
|
||||||
webServer: {
|
|
||||||
command: 'yarn dev',
|
|
||||||
url: 'http://127.0.0.1:8000',
|
|
||||||
reuseExistingServer: !process.env.CI,
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
|
||||||
projects: [
|
|
||||||
{
|
|
||||||
name: 'chromium',
|
|
||||||
use: { ...devices['Desktop Chrome'] },
|
|
||||||
},
|
|
||||||
|
|
||||||
// {
|
|
||||||
// name: 'firefox',
|
|
||||||
// use: { ...devices['Desktop Firefox'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
// {
|
|
||||||
// name: 'webkit',
|
|
||||||
// use: { ...devices['Desktop Safari'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against mobile viewports. */
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Chrome',
|
|
||||||
// use: { ...devices['Pixel 5'] },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Safari',
|
|
||||||
// use: { ...devices['iPhone 12'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against branded browsers. */
|
|
||||||
// {
|
|
||||||
// name: 'Microsoft Edge',
|
|
||||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Google Chrome',
|
|
||||||
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
})
|
|
|
@ -1,5 +0,0 @@
|
||||||
// Can't seem to make this work as ESM
|
|
||||||
const config = require('./shared/config/postcss.config.js')
|
|
||||||
|
|
||||||
module.exports = config
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import CopyToClipboard from 'shared/components/copy-to-clipboard'
|
|
||||||
|
|
||||||
const names = {
|
|
||||||
json: 'JSON',
|
|
||||||
yaml: 'YAML',
|
|
||||||
}
|
|
||||||
|
|
||||||
const Highlight = (props) => {
|
|
||||||
|
|
||||||
let language = 'txt'
|
|
||||||
if (props.language) language = props.language
|
|
||||||
if (props.children?.props?.className) {
|
|
||||||
language = props.children.props.className.split('-').pop()
|
|
||||||
}
|
|
||||||
const preProps = {
|
|
||||||
className: `language-${language} hljs text-base lg:text-lg whitespace-pre overflow-scroll pr-4`
|
|
||||||
}
|
|
||||||
if (props.raw) preProps.dangerouslySetInnerHTML = { __html: props.raw }
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="hljs my-4">
|
|
||||||
<div className={`
|
|
||||||
flex flex-row justify-between
|
|
||||||
text-xs uppercase font-bold text-neutral-content
|
|
||||||
mt-1 border-b border-neutral-content border-opacity-25
|
|
||||||
py-1 mb-2 lg:text-sm
|
|
||||||
`}>
|
|
||||||
<span> </span>
|
|
||||||
<span>{names[language] ? names[language] : language}</span>
|
|
||||||
<CopyToClipboard content={props.children} />
|
|
||||||
</div>
|
|
||||||
<pre {...preProps}>
|
|
||||||
{props.children}
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Highlight
|
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
// Handle themes
|
|
||||||
const themes = require('./shared/themes/index.js')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
content: [
|
|
||||||
'./pages/*.mjs',
|
|
||||||
'./pages/**/*.mjs',
|
|
||||||
'./shared/**/*.mjs',
|
|
||||||
'./lab/**/*.mjs',
|
|
||||||
// Legacy stuff, to be removed once everything is .mjs
|
|
||||||
'./pages/*.js',
|
|
||||||
'./pages/**/*.js',
|
|
||||||
'./shared/**/*.js',
|
|
||||||
'./lab/**/*.js',
|
|
||||||
],
|
|
||||||
plugins: [require('daisyui'), require('tailwindcss/nesting')],
|
|
||||||
daisyui: {
|
|
||||||
styled: true,
|
|
||||||
themes: [themes],
|
|
||||||
base: true,
|
|
||||||
utils: true,
|
|
||||||
logs: true,
|
|
||||||
rtl: false,
|
|
||||||
},
|
|
||||||
theme: {
|
|
||||||
extend: {
|
|
||||||
aspectRatio: {
|
|
||||||
'9/16': '9 / 16',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const parts = ['back', 'frontSideDart']
|
|
||||||
export const dependencies = ['@freesewing/bella']
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const parts = ['back', 'front', 'topSleeve', 'underSleeve']
|
|
||||||
export const dependencies = ['@freesewing/bent', '@freesewing/brian', '@freesewing/plugin-bust']
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const parts = ['back', 'front', 'sleeve']
|
|
||||||
export const dependencies = ['@freesewing/breanna']
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const parts = ['back', 'front', 'sleeve']
|
|
||||||
export const dependencies = ['@freesewing/brian', '@freesewing/plugin-bust']
|
|
|
@ -1,72 +0,0 @@
|
||||||
export const noInheritance = true
|
|
||||||
export const parts = [
|
|
||||||
{
|
|
||||||
part: 'box',
|
|
||||||
// this part uses the pluginBundle
|
|
||||||
pluginBundle: true,
|
|
||||||
// options needs to be a string of the internals of the options object
|
|
||||||
options: `size: { pct: 50, min: 10, max: 100 }`,
|
|
||||||
// the draft method needs all of these parameters uncommented
|
|
||||||
draftUses: {
|
|
||||||
options: true,
|
|
||||||
points: true,
|
|
||||||
paths: true,
|
|
||||||
Point: true,
|
|
||||||
Path: true,
|
|
||||||
complete: true,
|
|
||||||
paperless: true,
|
|
||||||
sa: true,
|
|
||||||
snippets: true,
|
|
||||||
Snippet: true,
|
|
||||||
macro: true,
|
|
||||||
},
|
|
||||||
// the draft method
|
|
||||||
draft: `// Add points to make a box
|
|
||||||
const w = 500 * options.size
|
|
||||||
points.topLeft = new Point(0, 0)
|
|
||||||
points.topRight = new Point(w, 0)
|
|
||||||
points.bottomLeft = new Point(0, w / 2)
|
|
||||||
points.bottomRight = new Point(w, w / 2)
|
|
||||||
|
|
||||||
// Create a path for the box outline
|
|
||||||
paths.seam = new Path()
|
|
||||||
.move(points.topLeft)
|
|
||||||
.line(points.bottomLeft)
|
|
||||||
.line(points.bottomRight)
|
|
||||||
.line(points.topRight)
|
|
||||||
.line(points.topLeft)
|
|
||||||
.close()
|
|
||||||
.setClass('fabric')
|
|
||||||
|
|
||||||
// Complete?
|
|
||||||
if (complete) {
|
|
||||||
// Add a logo
|
|
||||||
points.logo = points.topLeft.shiftFractionTowards(points.bottomRight, 0.5)
|
|
||||||
snippets.logo = new Snippet('logo', points.logo)
|
|
||||||
|
|
||||||
// Add some text
|
|
||||||
points.text = points.logo
|
|
||||||
.shift(-90, w / 8)
|
|
||||||
.addText('FreeSewing', 'center')
|
|
||||||
|
|
||||||
if (sa) {
|
|
||||||
// Add seam allowance
|
|
||||||
paths.sa = paths.seam.offset(sa).setClass('fabric sa')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add dimensions for paperless mode
|
|
||||||
if (paperless) {
|
|
||||||
macro('hd', {
|
|
||||||
from: points.bottomLeft,
|
|
||||||
to: points.bottomRight,
|
|
||||||
y: points.bottomLeft.y + sa + 15,
|
|
||||||
})
|
|
||||||
macro('vd', {
|
|
||||||
from: points.bottomRight,
|
|
||||||
to: points.topRight,
|
|
||||||
x: points.topRight.x + sa + 15,
|
|
||||||
})
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
]
|
|
|
@ -1,2 +0,0 @@
|
||||||
export const parts = ['back', 'front']
|
|
||||||
export const dependencies = ['@freesewing/titan', '@freesewing/snapseries']
|
|
|
@ -1,11 +0,0 @@
|
||||||
export const noInheritance = true
|
|
||||||
export const parts = [
|
|
||||||
{
|
|
||||||
part: 'bib',
|
|
||||||
// no draft method
|
|
||||||
draft: '',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// no additional dependencies
|
|
||||||
export const dependencies = []
|
|
|
@ -1,38 +0,0 @@
|
||||||
{{!
|
|
||||||
// Change the Mustache delimiter from double curly braces to double dollar signs.
|
|
||||||
// Dollar signs are allowed in EcmaScript identifier names,
|
|
||||||
// which is helpful when running unrendered Mustache templates through eslint.
|
|
||||||
//}}{{=$$ $$=}}
|
|
||||||
// Import Design constructor
|
|
||||||
import { Design } from '@freesewing/core'
|
|
||||||
// Import parts
|
|
||||||
$$#parts$$
|
|
||||||
import { $$.$$ } from './$$.$$.mjs'
|
|
||||||
$$/parts$$
|
|
||||||
|
|
||||||
// Create the new design
|
|
||||||
const $$Name$$ = new Design({
|
|
||||||
data: {
|
|
||||||
/*
|
|
||||||
* If you like, you can add any data you want to your design.
|
|
||||||
* We'll add the name here as an example.
|
|
||||||
*
|
|
||||||
* If you don't use this,
|
|
||||||
* you can remove this data key enterely.
|
|
||||||
*/
|
|
||||||
name: "$$ Name $$",
|
|
||||||
},
|
|
||||||
// A list of parts is all that is required.
|
|
||||||
parts: [ $$parts$$ ],
|
|
||||||
})
|
|
||||||
|
|
||||||
const Pattern = $$Name$$
|
|
||||||
/*
|
|
||||||
* Named exports
|
|
||||||
*
|
|
||||||
* We export the design itself as well as each part individually.
|
|
||||||
* This allows us to re-use these parts in other designs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export {$$#parts$$ $$.$$,$$/parts$$ $$Name$$, Pattern }
|
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
{{!
|
|
||||||
// Change the Mustache delimiter from double curly braces to double dollar signs.
|
|
||||||
// Dollar signs are allowed in EcmaScript identifier names,
|
|
||||||
// which is helpful when running unrendered Mustache templates through eslint.
|
|
||||||
//}}{{=$$ $$=}}
|
|
||||||
{
|
|
||||||
"name": "@freesewing/$$ name $$",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"description": "A new FreeSewing design",
|
|
||||||
"author": "Joost De Cock <joost@joost.at> (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",
|
|
||||||
"design",
|
|
||||||
"diy",
|
|
||||||
"fashion",
|
|
||||||
"parametric design",
|
|
||||||
"sewing",
|
|
||||||
"sewing pattern"
|
|
||||||
],
|
|
||||||
"main": "dist/index.js",
|
|
||||||
"module": "dist/index.mjs",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "next dev -p 8000",
|
|
||||||
"build": "node build.js",
|
|
||||||
"clean": "rimraf dist",
|
|
||||||
"mbuild": "NO_MINIFY=1 node build.js",
|
|
||||||
"test": "BABEL_ENV=production npx mocha tests/*.test.mjs --require @babel/register",
|
|
||||||
"vbuild": "VERBOSE=1 node build.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@freesewing/core": "$$ tag $$",
|
|
||||||
$$ #dependencies $$
|
|
||||||
"$$& . $$": "$$ tag $$",
|
|
||||||
$$ /dependencies $$
|
|
||||||
"@freesewing/plugin-bundle": "$$ tag $$"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@freesewing/plugin-annotations": "$$ tag $$",
|
|
||||||
"@freesewing/plugin-flip": "$$ tag $$",
|
|
||||||
"@freesewing/plugin-svgattr": "$$ tag $$",
|
|
||||||
"@freesewing/plugin-theme": "$$ tag $$",
|
|
||||||
"@freesewing/plugin-i18n": "$$ tag $$",
|
|
||||||
"@freesewing/plugin-mirror": "$$ tag $$",
|
|
||||||
"@freesewing/models": "$$ tag $$",
|
|
||||||
"@headlessui/react": "^1.6.5",
|
|
||||||
$$ #includeTests $$
|
|
||||||
"@playwright/test": "^1.32.3",
|
|
||||||
$$ /includeTests $$
|
|
||||||
"js-yaml": "^4.1.0",
|
|
||||||
"file-saver": "^2.0.5",
|
|
||||||
"axios": "^0.27.2",
|
|
||||||
"react": "^18.2.0",
|
|
||||||
"react-dom": "^18.2.0",
|
|
||||||
"react-sizeme": "^3.0.2",
|
|
||||||
"react-zoom-pan-pinch": "^2.1.3",
|
|
||||||
"react-markdown": "^8.0.3",
|
|
||||||
"roughjs": "^4.5.2",
|
|
||||||
"@tailwindcss/typography": "^0.5.2",
|
|
||||||
"d3-dispatch": "^3.0.1",
|
|
||||||
"d3-drag": "^3.0.0",
|
|
||||||
"d3-selection": "^3.0.0",
|
|
||||||
"daisyui": "^2.0.6",
|
|
||||||
"lodash.get": "^4.4.2",
|
|
||||||
"lodash.orderby": "^4.6.0",
|
|
||||||
"lodash.set": "^4.3.2",
|
|
||||||
"lodash.unset": "^4.5.2",
|
|
||||||
"lodash.clonedeep": "^4.5.0",
|
|
||||||
"next": "^13",
|
|
||||||
"mermaid": "10.1.0",
|
|
||||||
"next-i18next": "^11.0.0",
|
|
||||||
"pdfkit": "^0.13.0",
|
|
||||||
$$ #includeTests $$
|
|
||||||
"playwright": "^1.32.3",
|
|
||||||
$$ /includeTests $$
|
|
||||||
"react-copy-to-clipboard": "^5.0.4",
|
|
||||||
"react-hotkeys-hook": "^3.4.4",
|
|
||||||
"react-swipeable": "^6.2.0",
|
|
||||||
"react-timeago": "^7.1.0",
|
|
||||||
"mocha": "^9.1.1",
|
|
||||||
"chai": "^4.2.0",
|
|
||||||
"autoprefixer": "^10.4.0",
|
|
||||||
"eslint-config-next": "12.1.6",
|
|
||||||
"highlight.js": "^11.5.1",
|
|
||||||
"postcss": "^8.4.14",
|
|
||||||
"postcss-for": "^2.1.1",
|
|
||||||
"svg-to-pdfkit": "^0.1.8",
|
|
||||||
"tailwindcss": "^3.1.3",
|
|
||||||
"tailwindcss-open-variant": "^1.0.0",
|
|
||||||
"web-worker": "^1.2.0"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"dist/*",
|
|
||||||
"README.md",
|
|
||||||
"package.json"
|
|
||||||
],
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public",
|
|
||||||
"tag": "next"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16.0.0",
|
|
||||||
"npm": ">=8.3.0"
|
|
||||||
},
|
|
||||||
"overrides": {
|
|
||||||
"react-zoom-pan-pinch": {
|
|
||||||
"react": "$react",
|
|
||||||
"react-dom": "$react-dom"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
{{!
|
|
||||||
// Change the Mustache delimiter from double curly braces to double dollar signs.
|
|
||||||
// Dollar signs are allowed in EcmaScript identifier names,
|
|
||||||
// which is helpful when running unrendered Mustache templates through eslint.
|
|
||||||
//}}{{=$$ $$=}}
|
|
||||||
$$ #doesInherit $$
|
|
||||||
import { $$ part $$ as $$ baseName $$$$ Part $$ } from '@freesewing/$$ baseName $$'
|
|
||||||
|
|
||||||
$$ /doesInherit $$
|
|
||||||
$$ #pluginBundle $$
|
|
||||||
import { pluginBundle } from '@freesewing/plugin-bundle'
|
|
||||||
|
|
||||||
$$ /pluginBundle $$
|
|
||||||
function draft$$ Part $$ ({
|
|
||||||
// Uncomment below to destructure what you need
|
|
||||||
/*
|
|
||||||
* Content constructors
|
|
||||||
*/
|
|
||||||
$$ ^draftUses.Path $$//$$ /draftUses.Path $$Path, // A Path constructor to create new paths
|
|
||||||
$$ ^draftUses.Point $$//$$ /draftUses.Point $$Point, // A Point constructor to create new points
|
|
||||||
$$ ^draftUses.Snippet $$//$$ /draftUses.Snippet $$Snippet, // A Snippet constructor to create new snippets
|
|
||||||
/*
|
|
||||||
* Content constainers
|
|
||||||
*/
|
|
||||||
$$ ^draftUses.paths $$//$$ /draftUses.paths $$paths, // Add a Path to your part by adding it to this object
|
|
||||||
$$ ^draftUses.points $$//$$ /draftUses.points $$points, // Add a Points to your part by adding it to this object
|
|
||||||
$$ ^draftUses.snippets $$//$$ /draftUses.snippets $$snippets, // Add a Snippet to your part by adding it to this object
|
|
||||||
/*
|
|
||||||
* Access to settings
|
|
||||||
*/
|
|
||||||
$$ ^draftUses.absoluteOptions $$//$$ /draftUses.absoluteOptions $$absoluteOptions, // Access to settings.absoluteOptions
|
|
||||||
$$ ^draftUses.complete $$//$$ /draftUses.complete $$complete, // Access to settings.complete
|
|
||||||
$$ ^draftUses.measurements $$//$$ /draftUses.measurements $$measurements, // Access to settings.measurements
|
|
||||||
$$ ^draftUses.options $$//$$ /draftUses.options $$options, // Access to settings.options
|
|
||||||
$$ ^draftUses.paperless $$//$$ /draftUses.paperless $$paperless, // Access to settings.paperless
|
|
||||||
$$ ^draftUses.sa $$//$$ /draftUses.sa $$sa, // Access to settings.sa
|
|
||||||
$$ ^draftUses.scale $$//$$ /draftUses.scale $$scale, // Access to settings.scale
|
|
||||||
/*
|
|
||||||
* Access to utilities
|
|
||||||
*/
|
|
||||||
$$ ^draftUses.getId $$//$$ /draftUses.getId $$getId, //See the getId documentation
|
|
||||||
$$ ^draftUses.hide $$//$$ /draftUses.hide $$hide, //See the hide documentation
|
|
||||||
$$ ^draftUses.log $$//$$ /draftUses.log $$log, //See the logging documentation
|
|
||||||
$$ ^draftUses.macro $$//$$ /draftUses.macro $$macro, //See the macros documentation
|
|
||||||
$$ ^draftUses.setHidden $$//$$ /draftUses.setHidden $$setHidden, //See the setHidden documentation
|
|
||||||
$$ ^draftUses.store $$//$$ /draftUses.store $$store, //See the store documentation
|
|
||||||
$$ ^draftUses.unhide $$//$$ /draftUses.unhide $$unhide, //See the unhide documentation
|
|
||||||
$$ ^draftUses.units $$//$$ /draftUses.units $$units, //See the units documentation
|
|
||||||
/$$ ^draftUses.utils $$//$$ /draftUses.utils $$utils, //See the utils documentation
|
|
||||||
/*
|
|
||||||
* Return value
|
|
||||||
*/
|
|
||||||
part, // Your draft method must return this
|
|
||||||
}) {
|
|
||||||
$$& draft $$
|
|
||||||
$$ ^draft $$// Work your magic here $$ /draft $$
|
|
||||||
return part
|
|
||||||
}
|
|
||||||
|
|
||||||
export const $$ part $$ = {
|
|
||||||
/*
|
|
||||||
* name: Holds the name of this part.
|
|
||||||
*
|
|
||||||
* We STRONGLY recommend naming your parts in the format of
|
|
||||||
* design.part to avoid naming conflicts when people re-use
|
|
||||||
* parts across designs.
|
|
||||||
*/
|
|
||||||
name: '$$ name $$.$$ part $$',
|
|
||||||
/*
|
|
||||||
* draft: Holds the draft method for this part
|
|
||||||
*
|
|
||||||
* This should be a function that drafts and returns the part
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/draft
|
|
||||||
*/
|
|
||||||
draft: draft$$ Part $$,
|
|
||||||
after: [
|
|
||||||
/*
|
|
||||||
* after: Holds a list of parts that should be drafted prior to this part.
|
|
||||||
*
|
|
||||||
* You'll need to import these parts, just as with the from key above.
|
|
||||||
*
|
|
||||||
* If you don't have any parts to draft prior to this part,
|
|
||||||
* you can remove this options key entirely.
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/dependencies
|
|
||||||
*/
|
|
||||||
],
|
|
||||||
/*
|
|
||||||
* from: Holds the part you want to extend.
|
|
||||||
*
|
|
||||||
$$ #doesInherit $$
|
|
||||||
* Since you opted to extend $$ BaseName $$, and this is the $$ part $$ part,
|
|
||||||
* we're extending $$ BaseName $$'s $$ part $$ part here.
|
|
||||||
* It was imported at the top of this file from @freesewing/$$ BaseName $$
|
|
||||||
*
|
|
||||||
$$ /doesInherit $$
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/dependencies
|
|
||||||
*/
|
|
||||||
$$ #doesInherit $$
|
|
||||||
from: $$ baseName $$$$ Part $$,
|
|
||||||
$$ /doesInherit $$
|
|
||||||
$$ ^doesInherit $$
|
|
||||||
from: false,
|
|
||||||
$$ /doesInherit $$
|
|
||||||
/* hide: */
|
|
||||||
hide: {
|
|
||||||
/*
|
|
||||||
* self: Set this to true to hide the part.
|
|
||||||
*
|
|
||||||
* We've set this to false here to clarify its use.
|
|
||||||
* If you don't want to hide this part,
|
|
||||||
* you can remove the hide key entirely.
|
|
||||||
*/
|
|
||||||
self: false,
|
|
||||||
/*
|
|
||||||
* from: Set this to true to hide a part's from dependency.
|
|
||||||
*
|
|
||||||
$$ #doesInherit $$
|
|
||||||
* We've set this to true here since you're extending $$ BaseName $$'s $$ part $$ part.
|
|
||||||
$$ /doesInherit $$
|
|
||||||
* If you don't want to hide this part's from dependency,
|
|
||||||
* you can remove the from key entirely.
|
|
||||||
*/
|
|
||||||
from: $$ doesInherit $$,
|
|
||||||
/*
|
|
||||||
* after: Set this to true to hide any parts specified in the after setting
|
|
||||||
*
|
|
||||||
* We've set this to false here to clarify its use.
|
|
||||||
* If you don't want to hide this part,
|
|
||||||
* you can remove the hide key entirely.
|
|
||||||
*/
|
|
||||||
after: false
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
/*
|
|
||||||
* options: Holds (the configuration of) options for this part
|
|
||||||
*
|
|
||||||
* Declare options used in this part here.
|
|
||||||
$$ #doesInherit $$
|
|
||||||
* You only need to add additional options.
|
|
||||||
* All options coming from $$ BaseName $$'s $$ part $$ part are already loaded.
|
|
||||||
$$ /doesInherit $$
|
|
||||||
*
|
|
||||||
* If you don't have any options to add,
|
|
||||||
* you can remove this options key entirely.
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/options
|
|
||||||
*/
|
|
||||||
$$& options $$
|
|
||||||
},
|
|
||||||
measurements: [
|
|
||||||
/*
|
|
||||||
* measurements: Holds a list of measurements required by this part.
|
|
||||||
*
|
|
||||||
* Declare measurements required by this part here.
|
|
||||||
$$ #doesInherit $$
|
|
||||||
* You only need to add additional measurements.
|
|
||||||
* All measurements coming from $$ BaseName $$'s $$ part $$ part are already loaded.
|
|
||||||
$$ /doesInherit $$
|
|
||||||
*
|
|
||||||
* If you don't have any required measurements to add,
|
|
||||||
* you can remove this measurements key entirely.
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/measurements
|
|
||||||
*/
|
|
||||||
],
|
|
||||||
optionalMeasurements: [
|
|
||||||
/*
|
|
||||||
* optionalMeasurements: Holds a list of measurements optional in this part.
|
|
||||||
*
|
|
||||||
* Declare measurements that are optional for this part here.
|
|
||||||
*
|
|
||||||
* If you don't have any optional measurements to add,
|
|
||||||
* you can remove this optionalMeasurements key entirely.
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/measurements
|
|
||||||
*/
|
|
||||||
],
|
|
||||||
plugins: [
|
|
||||||
/*
|
|
||||||
* plugins: Holds a list of plugins this part relies on.
|
|
||||||
*
|
|
||||||
* Add all the plugins here that you need in this part.
|
|
||||||
$$ #doesInherit $$
|
|
||||||
* You only need to add additional plugins.
|
|
||||||
* All plugins coming from $$ BaseName $$'s $$ part $$ part are already loaded.
|
|
||||||
$$ /doesInherit $$
|
|
||||||
*
|
|
||||||
* If you don't have any plugins to add,
|
|
||||||
* you can remove this plugins key entirely.
|
|
||||||
*
|
|
||||||
* Documentation: https://freesewing.dev/reference/api/part/config/plugins
|
|
||||||
*/
|
|
||||||
$$ #pluginBundle $$
|
|
||||||
pluginBundle,
|
|
||||||
$$ /pluginBundle $$
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,11 +1,57 @@
|
||||||
import configBuilder from '../shared/config/next.mjs'
|
import path from 'path'
|
||||||
import i18nConfig from './next-i18next.config.js'
|
// Remark plugins
|
||||||
import { banner } from '../../scripts/banner.mjs'
|
import remarkFrontmatter from 'remark-frontmatter'
|
||||||
|
import remarkMdxFrontmatter from 'remark-mdx-frontmatter'
|
||||||
|
import remarkGfm from 'remark-gfm'
|
||||||
|
import smartypants from 'remark-smartypants'
|
||||||
|
|
||||||
let config = configBuilder({ site: 'sde' })
|
/*
|
||||||
config.i18n = i18nConfig.i18n
|
* This is the NextJS configuration
|
||||||
|
*/
|
||||||
|
const config = {
|
||||||
|
experimental: {
|
||||||
|
externalDir: true,
|
||||||
|
},
|
||||||
|
pageExtensions: ['mjs'],
|
||||||
|
webpack: (config, options) => {
|
||||||
|
// Fixes npm packages that depend on node modules
|
||||||
|
if (!options.isServer) {
|
||||||
|
config.resolve.fallback.fs = false
|
||||||
|
config.resolve.fallback.path = false
|
||||||
|
config.resolve.fallback.child_process = false
|
||||||
|
}
|
||||||
|
|
||||||
// Say hi
|
// MDX support
|
||||||
console.log(banner + '\n')
|
config.module.rules.push({
|
||||||
|
test: /\.mdx?$/,
|
||||||
|
use: [
|
||||||
|
options.defaultLoaders.babel,
|
||||||
|
{
|
||||||
|
loader: '@mdx-js/loader',
|
||||||
|
options: {
|
||||||
|
providerImportSource: '@mdx-js/react',
|
||||||
|
format: 'mdx',
|
||||||
|
remarkPlugins: [remarkFrontmatter, remarkMdxFrontmatter, remarkGfm, smartypants],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
// Fix for nextjs bug #17806
|
||||||
|
config.module.rules.push({
|
||||||
|
test: /index.mjs$/,
|
||||||
|
type: 'javascript/auto',
|
||||||
|
resolve: {
|
||||||
|
fullySpecified: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Aliases
|
||||||
|
config.resolve.alias.shared = path.resolve('./shared/')
|
||||||
|
config.resolve.alias.site = path.resolve(`./`)
|
||||||
|
|
||||||
|
return config
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
|
|
|
@ -15,19 +15,61 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"cibuild": "yarn build",
|
|
||||||
"dev": "next dev -p 8000",
|
"dev": "next dev -p 8000",
|
||||||
"develop": "next dev -p 8000",
|
"develop": "next dev -p 8000",
|
||||||
"i18n": "SITE=sde node --conditions=internal ../shared/prebuild/i18n-only.mjs",
|
"lint": "next lint"
|
||||||
"lint": "next lint",
|
|
||||||
"prebuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs",
|
|
||||||
"start": "yarn prebuild && yarn dev",
|
|
||||||
"wbuild": "next build",
|
|
||||||
"prewbuild": "node --conditions=internal --experimental-json-modules ./prebuild.mjs"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {},
|
"peerDependencies": {},
|
||||||
"dependencies": {},
|
"dependencies": {
|
||||||
"devDependencies": {},
|
"@freesewing/core": "next",
|
||||||
|
"@freesewing/core-plugins": "next",
|
||||||
|
"@freesewing/brian": "next",
|
||||||
|
"@freesewing/titan": "next",
|
||||||
|
"@freesewing/bella": "next",
|
||||||
|
"@freesewing/breanna": "next",
|
||||||
|
"@headlessui/react": "1.7.17",
|
||||||
|
"@mdx-js/loader": "2.3.0",
|
||||||
|
"@mdx-js/mdx": "2.3.0",
|
||||||
|
"@mdx-js/react": "2.3.0",
|
||||||
|
"@mdx-js/runtime": "2.0.0-next.9",
|
||||||
|
"@tailwindcss/typography": "0.5.9",
|
||||||
|
"d3-dispatch": "3.0.1",
|
||||||
|
"d3-drag": "3.0.0",
|
||||||
|
"d3-selection": "3.0.0",
|
||||||
|
"daisyui": "3.6.4",
|
||||||
|
"i18next": "23.4.6",
|
||||||
|
"lodash.get": "4.4.2",
|
||||||
|
"lodash.orderby": "4.6.0",
|
||||||
|
"lodash.set": "4.3.2",
|
||||||
|
"next": "13.4.19",
|
||||||
|
"next-i18next": "14.0.0",
|
||||||
|
"react": "18.2.0",
|
||||||
|
"react-dom": "18.2.0",
|
||||||
|
"react-copy-to-clipboard": "5.1.0",
|
||||||
|
"react-hotkeys-hook": "4.4.1",
|
||||||
|
"react-i18next": "13.2.2",
|
||||||
|
"react-markdown": "8.0.7",
|
||||||
|
"react-swipeable": "7.0.1",
|
||||||
|
"react-timeago": "7.1.0",
|
||||||
|
"rehype-autolink-headings": "6.1.1",
|
||||||
|
"rehype-highlight": "6.0.0",
|
||||||
|
"rehype-sanitize": "5.0.1",
|
||||||
|
"rehype-slug": "5.1.0",
|
||||||
|
"rehype-stringify": "10.0.0",
|
||||||
|
"remark-smartypants": "2.0.0",
|
||||||
|
"remark-copy-linked-files": "git+https://git@github.com/joostdecock/remark-copy-linked-files",
|
||||||
|
"remark-gfm": "3.0.1",
|
||||||
|
"remark-mdx-frontmatter": "3.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"autoprefixer": "10.4.15",
|
||||||
|
"eslint-config-next": "13.4.19",
|
||||||
|
"js-yaml": "4.1.0",
|
||||||
|
"postcss": "8.4.29",
|
||||||
|
"remark-extract-frontmatter": "3.2.0",
|
||||||
|
"remark-mdx-frontmatter": "3.0.0",
|
||||||
|
"tailwindcss": "3.3.3"
|
||||||
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18",
|
"node": "18",
|
||||||
"npm": "9"
|
"npm": "9"
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
["plugin-bundle", "plugin-bust"]
|
|
Loading…
Add table
Add a link
Reference in a new issue