feat: Migrated to React 19
This commit is contained in:
parent
0a9c3d9473
commit
9ab297a471
502 changed files with 16459 additions and 21191 deletions
|
@ -13,6 +13,9 @@ _types:
|
|||
dev:
|
||||
'mocha': *mocha
|
||||
'chai': *chai
|
||||
#
|
||||
# Designs
|
||||
#
|
||||
aaron:
|
||||
peer:
|
||||
'@freesewing/brian': *freesewing
|
||||
|
@ -45,21 +48,6 @@ charlie:
|
|||
peer:
|
||||
'@freesewing/titan': *freesewing
|
||||
'@freesewing/snapseries': *freesewing
|
||||
core:
|
||||
_:
|
||||
'@freesewing/core-plugins': *freesewing
|
||||
'bezier-js': '6.1.4'
|
||||
'hooks': '0.3.2'
|
||||
'lodash.get': &_get '4.4.2'
|
||||
'lodash.set': &_set '4.3.2'
|
||||
'lodash.unset': &_unset '4.5.2'
|
||||
'lodash.clonedeep': '^4.5.0'
|
||||
dev:
|
||||
'eslint': &eslint '8.57.0'
|
||||
'nyc': '17.1.0'
|
||||
'mocha': *mocha
|
||||
'chai': *chai
|
||||
'sinon': &sinon '^18.0.0'
|
||||
diana:
|
||||
peer:
|
||||
'@freesewing/brian': *freesewing
|
||||
|
@ -89,15 +77,6 @@ lily:
|
|||
peer:
|
||||
'@freesewing/titan': *freesewing
|
||||
'@freesewing/paco': *freesewing
|
||||
new-design:
|
||||
_:
|
||||
'axios': &axios '1.7.2'
|
||||
'chalk': '5.3.0'
|
||||
'execa': '9.2.0'
|
||||
'mustache': &mustache '4.2.0'
|
||||
'ora': &ora '8.0.1'
|
||||
'prompts': '2.4.2'
|
||||
'recursive-readdir': '2.2.3'
|
||||
noble:
|
||||
peer:
|
||||
'@freesewing/bella': *freesewing
|
||||
|
@ -105,12 +84,6 @@ paco:
|
|||
peer:
|
||||
'@freesewing/titan': *freesewing
|
||||
'@freesewing/snapseries': *freesewing
|
||||
core-plugins:
|
||||
dev:
|
||||
'@freesewing/plugin-annotations': *freesewing
|
||||
'@freesewing/plugin-mirror': *freesewing
|
||||
'@freesewing/plugin-round': *freesewing
|
||||
'@freesewing/plugin-sprinkle': *freesewing
|
||||
plugintest:
|
||||
peer:
|
||||
'@freesewing/plugin-annotations': *freesewing
|
||||
|
@ -124,26 +97,6 @@ plugintest:
|
|||
'@freesewing/plugin-sprinkle': *freesewing
|
||||
'@freesewing/plugin-svgattr': *freesewing
|
||||
'@freesewing/plugin-theme': *freesewing
|
||||
react:
|
||||
_:
|
||||
axios: *axios
|
||||
highlight.js: "^11.11.0"
|
||||
html-react-parser: "^5.0.7"
|
||||
luxon: "^3.5.0"
|
||||
nuqs: "^1.17.6"
|
||||
react-markdown: "^9.0.1"
|
||||
tlds: "^1.255.0"
|
||||
use-local-storage-state: "19.1.0"
|
||||
use-session-storage-state: "^19.0.0"
|
||||
peer:
|
||||
react: "^18.2.0"
|
||||
rehype-jargon:
|
||||
_:
|
||||
'unist-util-visit': &unist-util-visit '5.0.0'
|
||||
'hast-util-from-html': '2.0.1'
|
||||
rehype-highlight-lines:
|
||||
_:
|
||||
'unist-util-remove': '4.0.0'
|
||||
sandy:
|
||||
peer:
|
||||
'@freesewing/snapseries': *freesewing
|
||||
|
@ -187,6 +140,34 @@ yuri:
|
|||
'@freesewing/brian': *freesewing
|
||||
'@freesewing/plugin-bust': *freesewing
|
||||
|
||||
#
|
||||
# Plugins
|
||||
#
|
||||
core-plugins:
|
||||
dev:
|
||||
'@freesewing/plugin-annotations': *freesewing
|
||||
'@freesewing/plugin-mirror': *freesewing
|
||||
'@freesewing/plugin-round': *freesewing
|
||||
'@freesewing/plugin-sprinkle': *freesewing
|
||||
|
||||
#
|
||||
# Packages
|
||||
#
|
||||
core:
|
||||
_:
|
||||
'@freesewing/core-plugins': *freesewing
|
||||
'bezier-js': '6.1.4'
|
||||
'hooks': '0.3.2'
|
||||
'lodash.get': &_get '4.4.2'
|
||||
'lodash.set': &_set '4.3.2'
|
||||
'lodash.unset': &_unset '4.5.2'
|
||||
'lodash.clonedeep': '^4.5.0'
|
||||
dev:
|
||||
'eslint': &eslint '8.57.0'
|
||||
'nyc': '17.1.0'
|
||||
'mocha': *mocha
|
||||
'chai': *chai
|
||||
'sinon': &sinon '^18.0.0'
|
||||
collection:
|
||||
_:
|
||||
# Designs
|
||||
|
@ -255,220 +236,26 @@ collection:
|
|||
# Other
|
||||
'@freesewing/core': *freesewing
|
||||
'@freesewing/snapseries': *freesewing
|
||||
|
||||
# Sites go here
|
||||
|
||||
backend:
|
||||
react:
|
||||
_:
|
||||
'@aws-sdk/client-sesv2': '3.592.0'
|
||||
'@prisma/client': &prisma '5.15.0'
|
||||
'bcryptjs': '2.4.3'
|
||||
'cors': '2.8.5'
|
||||
'dotenv': '16.4.5'
|
||||
'express': '4.19.2'
|
||||
'js-yaml': &jsyaml '4.1.0'
|
||||
'lodash.get': *_get
|
||||
'mustache': *mustache
|
||||
'otplib': '12.0.1'
|
||||
'passport': '0.7.0'
|
||||
'passport-http': '0.3.0'
|
||||
'passport-jwt': '4.0.1'
|
||||
'pino': '9.2.0'
|
||||
'qrcode': '1.5.3'
|
||||
'swagger-ui-dist': '5.17.10'
|
||||
'swagger-ui-express': '5.0.0'
|
||||
dev:
|
||||
'chai': *chai
|
||||
'chai-http': '5.1.1'
|
||||
'esbuild': '0.21.3'
|
||||
'mocha': *mocha
|
||||
'mocha-steps': '1.3.0'
|
||||
'nodemon': '3.1.0'
|
||||
'prisma': *prisma
|
||||
|
||||
dev:
|
||||
"@uiw/react-codemirror": "^4.23.8"
|
||||
d3-drag: "3.0.0"
|
||||
d3-selection: "3.0.0"
|
||||
file-saver: "^2.0.5"
|
||||
"highlight.js": "^11.11.1"
|
||||
html-react-parser: "^5.2.2"
|
||||
jotai: "^2.12.1"
|
||||
jotai-location: "^0.5.5"
|
||||
luxon: "^3.5.0"
|
||||
pdfkit: "^0.16.0"
|
||||
react-dropzone: "^14.3.5"
|
||||
react-zoom-pan-pinch: "^3.7.0"
|
||||
svg-to-pdfkit: "^0.1.8"
|
||||
use-local-storage-state: "^19.5.0"
|
||||
web-worker: "^1.5.0"
|
||||
peer:
|
||||
react: &react "^19.0.0"
|
||||
utils:
|
||||
_:
|
||||
'@mdx-js/mdx': &mdx '^3.0.0'
|
||||
'@mdx-js/react': *mdx
|
||||
'@mdx-js/runtime': &mdxRuntime '2.0.0-next.9'
|
||||
'@next/bundle-analyzer': &next '14.2.3'
|
||||
'@tailwindcss/typography': &tailwindTypography '0.5.13'
|
||||
'algoliasearch': &algoliasearch '4.23.3'
|
||||
'daisyui': &daisyui '4.11.1'
|
||||
'lodash.get': *_get
|
||||
'lodash.orderby': &_orderby '4.6.0'
|
||||
'lodash.set': *_set
|
||||
'next': *next
|
||||
'react': &react '18.3.1'
|
||||
'react-copy-to-clipboard': &reactCopyToClipboard '5.1.0'
|
||||
'react-dom': *react
|
||||
'react-hotkeys-hook': &reactHotkeysHook '4.5.0'
|
||||
'react-instantsearch-dom': &reactInstantsearchDom '6.40.4'
|
||||
'react-instantsearch-hooks-web': &reactInstantsearchHooksWeb '6.47.3'
|
||||
'react-swipeable': &reactSwipeable '7.0.1'
|
||||
'react-timeago': &reactTimeago '7.2.0'
|
||||
'rehype-autolink-headings': &rehypeAutolinkHeadings '7.1.0'
|
||||
'rehype-highlight': &rehypeHighlight '7.0.0'
|
||||
'rehype-sanitize': &rehypeSanitize '6.0.0'
|
||||
'rehype-slug': &rehypeSlug '6.0.0'
|
||||
'rehype-stringify': &rehypeStringify '10.0.1'
|
||||
'remark': &remark 15.0.1
|
||||
# see: https://github.com/npm/cli/issues/2610#issuecomment-1295371753
|
||||
'remark-copy-linked-files': &remarkCopyLinkedFiles 'git+https://git@github.com/joostdecock/remark-copy-linked-files'
|
||||
'remark-gfm': &remarkGfm '4.0.0'
|
||||
'strip-markdown': &stripMarkdown 6.0.0
|
||||
dev: &nextSiteDevDependencies
|
||||
'autoprefixer': &autoprefixer '10.4.19'
|
||||
'js-yaml': &jsYaml '4.1.0'
|
||||
'postcss': &postcss '8.4.38'
|
||||
'remark-extract-frontmatter': '3.2.0'
|
||||
'remark-mdx-frontmatter': &mdxfrontmatter '5.0.0'
|
||||
'tailwindcss': &tailwindcss '3.4.3'
|
||||
'yaml-loader': '0.8.1'
|
||||
"@babel/preset-react": "^7.26.3"
|
||||
|
||||
lab:
|
||||
_:
|
||||
'@mdx-js/mdx': *mdx
|
||||
'@mdx-js/react': *mdx
|
||||
'@mdx-js/runtime': *mdxRuntime
|
||||
'@tailwindcss/typography': *tailwindTypography
|
||||
'algoliasearch': *algoliasearch
|
||||
'd3-dispatch': &d3dispatch '3.0.1'
|
||||
'd3-drag': &d3drag '3.0.0'
|
||||
'd3-selection': &d3selection '3.0.0'
|
||||
'daisyui': *daisyui
|
||||
'i18next': &i18next '23.11.5'
|
||||
'lodash.get': *_get
|
||||
'lodash.orderby': *_orderby
|
||||
'lodash.set': *_set
|
||||
'next': *next
|
||||
'next-i18next': &nextI18next '15.3.0'
|
||||
'ora': *ora
|
||||
'react': *react
|
||||
'react-copy-to-clipboard': *reactCopyToClipboard
|
||||
'react-hotkeys-hook': *reactHotkeysHook
|
||||
'react-i18next': &reactI18next '14.1.2'
|
||||
'react-instantsearch-dom': *reactInstantsearchDom
|
||||
'react-swipeable': *reactSwipeable
|
||||
'react-timeago': *reactTimeago
|
||||
'rehype-autolink-headings': *rehypeAutolinkHeadings
|
||||
'rehype-highlight': *rehypeHighlight
|
||||
'rehype-sanitize': *rehypeSanitize
|
||||
'rehype-slug': *rehypeSlug
|
||||
'rehype-stringify': *rehypeStringify
|
||||
'remark-copy-linked-files': *remarkCopyLinkedFiles
|
||||
'remark-gfm': *remarkGfm
|
||||
'remark-mdx-frontmatter': *mdxfrontmatter
|
||||
dev:
|
||||
*nextSiteDevDependencies
|
||||
|
||||
org:
|
||||
_:
|
||||
'@bugsnag/js': &bugsnag 7.23.0
|
||||
'@bugsnag/plugin-react': 8.1.1
|
||||
'@mdx-js/mdx': *mdx
|
||||
'@mdx-js/react': *mdx
|
||||
'@mdx-js/runtime': *mdxRuntime
|
||||
"@tailwindcss/nesting": &twnesting "^0.0.0-insiders.565cd3e"
|
||||
'@tailwindcss/typography': *tailwindTypography
|
||||
'algoliasearch': *algoliasearch
|
||||
'react-copy-to-clipboard': *reactCopyToClipboard
|
||||
'daisyui': *daisyui
|
||||
'echarts': &echarts 5.5.0
|
||||
'echarts-for-react': &echartsReact 3.0.2
|
||||
'jotai': &jotai '2.8.3'
|
||||
'jotai-location': &jotai-location '0.5.5'
|
||||
'lodash.get': *_get
|
||||
'lodash.orderby': *_orderby
|
||||
'lodash.set': *_set
|
||||
'luxon': '3.5.0'
|
||||
'next': *next
|
||||
'next-i18next': *nextI18next
|
||||
'ora': *ora
|
||||
'react': *react
|
||||
'react-dom': *react
|
||||
'react-dropzone': &dropzone '14.2.3'
|
||||
'react-hotkeys-hook': *reactHotkeysHook
|
||||
"react-i18next": *reactI18next
|
||||
'react-instantsearch-dom': *reactInstantsearchDom
|
||||
'react-instantsearch-hooks-web': *reactInstantsearchHooksWeb
|
||||
'react-swipeable': *reactSwipeable
|
||||
'react-timeago': *reactTimeago
|
||||
'react-zoom-pan-pinch': &zoompanpinch '3.4.4'
|
||||
'rehype-autolink-headings': *rehypeAutolinkHeadings
|
||||
'rehype-highlight': *rehypeHighlight
|
||||
'rehype-sanitize': *rehypeSanitize
|
||||
'rehype-slug': *rehypeSlug
|
||||
'rehype-stringify': *rehypeStringify
|
||||
'remark': *remark
|
||||
'remark-copy-linked-files': *remarkCopyLinkedFiles
|
||||
'remark-gfm': *remarkGfm
|
||||
'remark-mdx-frontmatter': *mdxfrontmatter
|
||||
'strip-markdown': *stripMarkdown
|
||||
'use-local-storage-state': &use-local-storage-state 19.2.0
|
||||
'yaml-loader': 0.8.1
|
||||
dev: *nextSiteDevDependencies
|
||||
|
||||
sde:
|
||||
_:
|
||||
"@freesewing/core": *freesewing
|
||||
"@freesewing/core-plugins": *freesewing
|
||||
"@freesewing/brian": *freesewing
|
||||
"@freesewing/bent": *freesewing
|
||||
"@freesewing/titan": *freesewing
|
||||
"@freesewing/bella": *freesewing
|
||||
"@freesewing/breanna": *freesewing
|
||||
"@freesewing/plugin-bust": *freesewing
|
||||
"@freesewing/plugin-timing": *freesewing
|
||||
"@freesewing/plugin-theme": *freesewing
|
||||
"@freesewing/plugin-i18n": *freesewing
|
||||
"@freesewing/snapseries": *freesewing
|
||||
"@freesewing/react": *freesewing
|
||||
'@mdx-js/mdx': *mdx
|
||||
'@mdx-js/react': *mdx
|
||||
'@mdx-js/runtime': *mdxRuntime
|
||||
"@tailwindcss/nesting": *twnesting
|
||||
'@tailwindcss/typography': *tailwindTypography
|
||||
'autoprefixer': *autoprefixer
|
||||
'axios': *axios
|
||||
'd3-dispatch': *d3dispatch
|
||||
'd3-drag': *d3drag
|
||||
'd3-selection': *d3selection
|
||||
'daisyui': *daisyui
|
||||
'echarts': *echarts
|
||||
'echarts-for-react': *echartsReact
|
||||
'file-saver': latest
|
||||
'i18next': *i18next
|
||||
'jotai': *jotai
|
||||
'jotai-location': *jotai-location
|
||||
'js-yaml': *jsyaml
|
||||
'lodash.debounce': latest
|
||||
'lodash.get': *_get
|
||||
'lodash.orderby': *_orderby
|
||||
'lodash.set': *_set
|
||||
'mustache': *mustache
|
||||
"next": *next
|
||||
'next-i18next': *nextI18next
|
||||
'pdfkit': latest
|
||||
'postcss-for': latest
|
||||
"react": *react
|
||||
"react-dom": *react
|
||||
'react-copy-to-clipboard': *reactCopyToClipboard
|
||||
'react-hotkeys-hook': *reactHotkeysHook
|
||||
"react-i18next": *reactI18next
|
||||
'react-dropzone': *dropzone
|
||||
'react-swipeable': *reactSwipeable
|
||||
'react-timeago': *reactTimeago
|
||||
'react-zoom-pan-pinch': *zoompanpinch
|
||||
'remark-gfm': *remarkGfm
|
||||
'remark-frontmatter': latest
|
||||
'remark-mdx-frontmatter': *mdxfrontmatter
|
||||
'remark-smartypants': latest
|
||||
"slugify": latest
|
||||
'svg-to-pdfkit': latest
|
||||
'tailwindcss': *tailwindcss
|
||||
'tlds': latest
|
||||
'use-local-storage-state': *use-local-storage-state
|
||||
'web-worker': latest
|
||||
|
||||
lodash: "^4.17.21"
|
||||
tlds: "^1.255.0"
|
||||
|
|
|
@ -79,7 +79,7 @@ packageJson:
|
|||
"./components/Button": "./components/Button/index.mjs"
|
||||
"./components/Collection": "./components/Collection/index.mjs"
|
||||
"./components/Control": "./components/Control/index.mjs"
|
||||
"./components/CopyToClipboard": "./components/CopyToClipboard/index.mjs"
|
||||
"./components/CopyToClipboardButton": "./components/CopyToClipboardButton/index.mjs"
|
||||
"./components/Design": "./components/Design/index.mjs"
|
||||
"./components/Docusaurus": "./components/Docusaurus/index.mjs"
|
||||
"./components/Editor": "./components/Editor/index.mjs"
|
||||
|
|
|
@ -8,7 +8,5 @@
|
|||
"prettier-config": "FreeSewing's shared configuration for prettier",
|
||||
"react": "React components, hooks and context by/for FreeSewing",
|
||||
"snapseries": "A series of common sizes for elastics and other series to be used with snapped percentage options",
|
||||
"utils": "A number of utilities, typically used by FreeSewing frontend code",
|
||||
"rehype-jargon": "A Rehype plugin for jargon terms",
|
||||
"rehype-highlight-lines": "A Rehype plugin to add highlighted lines to code blocks"
|
||||
"utils": "A number of utilities, typically used by FreeSewing frontend code"
|
||||
}
|
||||
|
|
33002
package-lock.json
generated
33002
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -60,7 +60,6 @@
|
|||
"all-contributors-cli": "^6.26.1",
|
||||
"axios": "^1.5.1",
|
||||
"chalk": "^4.1.0",
|
||||
"codecov": "^3.8.3",
|
||||
"cross-env": "^7.0.2",
|
||||
"eslint": "^8.23.1",
|
||||
"eslint-plugin-jsonc": "^2.4.0",
|
||||
|
@ -78,8 +77,6 @@
|
|||
"nyc": "^15.1.0",
|
||||
"prettier": "^3.0.0",
|
||||
"pretty-quick": "^4.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^18.2.0",
|
||||
"rimraf": "^5.0.0",
|
||||
"standard": "^17.0.0"
|
||||
},
|
||||
|
@ -98,7 +95,8 @@
|
|||
"eslint-config-next": "^14.0.1",
|
||||
"glob": "^10.3.10",
|
||||
"rehype-format": "^5.0.0",
|
||||
"rehype-stringify": "^10.0.1"
|
||||
"rehype-stringify": "^10.0.1",
|
||||
"tlds": "^1.255.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0"
|
||||
|
|
|
@ -24,15 +24,7 @@
|
|||
"lint": "npx eslint 'lib/*.mjs'"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"dependencies": {
|
||||
"axios": "1.7.2",
|
||||
"chalk": "5.3.0",
|
||||
"execa": "9.2.0",
|
||||
"mustache": "4.2.0",
|
||||
"ora": "8.0.1",
|
||||
"prompts": "2.4.2",
|
||||
"recursive-readdir": "2.2.3"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"files": [
|
||||
"README.md",
|
||||
|
|
|
@ -29,7 +29,7 @@ import { ModalWrapper } from '@freesewing/react/components/Modal'
|
|||
import { NumberCircle } from '@freesewing/react/components/Number'
|
||||
import { StringInput, FormControl, ListInput } from '@freesewing/react/components/Input'
|
||||
import { DisplayRow } from './shared.mjs'
|
||||
import { CopyToClipboard } from '@freesewing/react/components/CopyToClipboard'
|
||||
import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton'
|
||||
import { TimeAgo, TimeToGo } from '@freesewing/react/components/Time'
|
||||
import { KeyVal } from '@freesewing/react/components/KeyVal'
|
||||
|
||||
|
@ -303,12 +303,12 @@ const ShowNewApikey = ({ apikey }) => (
|
|||
</div>
|
||||
<h6 className="tw-flex tw-flex-row tw-items-center">
|
||||
Key
|
||||
<CopyToClipboard sup content={apikey.key} label="API key ID" />
|
||||
<CopyToClipboardButton sup content={apikey.key} label="API key ID" />
|
||||
</h6>
|
||||
<pre>{apikey.key}</pre>
|
||||
<h6 className="tw-flex tw-flex-row tw-items-center">
|
||||
Secret
|
||||
<CopyToClipboard sup content={apikey.secret} label="API key secret" />
|
||||
<CopyToClipboardButton sup content={apikey.secret} label="API key secret" />
|
||||
</h6>
|
||||
<pre>{apikey.secret}</pre>
|
||||
<Popout warning compact>
|
||||
|
|
|
@ -16,7 +16,7 @@ import { NoIcon, LockIcon } from '@freesewing/react/components/Icon'
|
|||
import { PasswordInput } from '@freesewing/react/components/Input'
|
||||
import { Popout } from '@freesewing/react/components/Popout'
|
||||
import { NumberCircle } from '@freesewing/react/components/Number'
|
||||
import { CopyToClipboard } from '@freesewing/react/components/CopyToClipboard'
|
||||
import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton'
|
||||
|
||||
/*
|
||||
* Component for the account/security/password page
|
||||
|
@ -166,7 +166,7 @@ export const Mfa = ({ welcome = false, title = true }) => {
|
|||
<div className="hljs tw-my-4">
|
||||
<div className="tw-flex tw-flex-row tw-justify-between tw-items-center tw-text-xs tw-font-medium tw-text-warning tw-mt-1 tw-border-b tw-border-neutral-content tw-border-opacity-25 tw-px-4 tw-py-1 tw-mb-2 lg:tw-text-sm">
|
||||
<span>MFA Scratch Codes</span>
|
||||
<CopyToClipboard
|
||||
<CopyToClipboardButton
|
||||
content={
|
||||
'FreeSewing MFA Scratch Codes:\n' +
|
||||
scratchCodes.map((code) => code + '\n').join('')
|
||||
|
|
|
@ -42,7 +42,6 @@ import {
|
|||
import { IconButton } from '@freesewing/react/components/Button'
|
||||
import { ModalWrapper } from '@freesewing/react/components/Modal'
|
||||
import { KeyVal } from '@freesewing/react/components/KeyVal'
|
||||
import { CopyToClipboard as Copy } from 'react-copy-to-clipboard'
|
||||
|
||||
const filterAtom = atomWithHash('filter', { example: true })
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useContext, useState } from 'react'
|
||||
import { copyToClipboard } from '@freesewing/utils'
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import { CopyIcon, OkIcon } from '@freesewing/react/components/Icon'
|
||||
import { CopyToClipboard as Copy } from 'react-copy-to-clipboard'
|
||||
import { LoadingStatusContext } from '@freesewing/react/context/LoadingStatus'
|
||||
|
||||
const strip = (html) =>
|
||||
|
@ -9,7 +9,8 @@ const strip = (html) =>
|
|||
? html
|
||||
: new DOMParser().parseFromString(html, 'text/html').body.textContent || ''
|
||||
|
||||
const handleCopied = (setCopied, setLoadingStatus, label) => {
|
||||
const handleCopied = (content, setCopied, setLoadingStatus, label) => {
|
||||
copyToClipboard(content)
|
||||
setCopied(true)
|
||||
setLoadingStatus([
|
||||
true,
|
||||
|
@ -20,7 +21,7 @@ const handleCopied = (setCopied, setLoadingStatus, label) => {
|
|||
setTimeout(() => setCopied(false), 1000)
|
||||
}
|
||||
|
||||
export const CopyToClipboard = ({ content, label = false, sup = false }) => {
|
||||
export const CopyToClipboardButton = ({ content, label = false, sup = false }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const { setLoadingStatus } = useContext(LoadingStatusContext)
|
||||
|
||||
|
@ -30,8 +31,10 @@ export const CopyToClipboard = ({ content, label = false, sup = false }) => {
|
|||
const style = sup ? 'tw-w-4 tw-h-4 tw--mt-4' : 'tw-w-5 tw-h-5'
|
||||
|
||||
return (
|
||||
<Copy text={text} onCopy={() => handleCopied(setCopied, setLoadingStatus, label)}>
|
||||
<button className={copied ? 'tw-text-success' : ''}>
|
||||
<button
|
||||
className={copied ? 'tw-text-success' : ''}
|
||||
onClick={() => handleCopied(content, setCopied, setLoadingStatus, label)}
|
||||
>
|
||||
{copied ? (
|
||||
<OkIcon
|
||||
className={`${style} tw-text-success-content tw-bg-success tw-rounded-full tw-p-1`}
|
||||
|
@ -41,6 +44,5 @@ export const CopyToClipboard = ({ content, label = false, sup = false }) => {
|
|||
<CopyIcon className={`${style} tw-text-inherit`} />
|
||||
)}
|
||||
</button>
|
||||
</Copy>
|
||||
)
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
import React, { useContext, useState } from 'react'
|
||||
import ReactDOMServer from 'react-dom/server'
|
||||
import { horFlexClasses } from '@freesewing/utils'
|
||||
import { CopyIcon, OkIcon } from '@freesewing/react/components/Icon'
|
||||
import { CopyToClipboard as Copy } from 'react-copy-to-clipboard'
|
||||
|
||||
const strip = (html) =>
|
||||
typeof DOMParser === 'undefined'
|
||||
? html
|
||||
: new DOMParser().parseFromString(html, 'text/html').body.textContent || ''
|
||||
|
||||
const handleCopied = (setCopied, label, update) => {
|
||||
setCopied(true)
|
||||
update.notifySuccess(label ? `${label} c` : 'C' + 'opied to clipboard')
|
||||
setTimeout(() => setCopied(false), 1000)
|
||||
}
|
||||
|
||||
export const CopyToClipboard = ({ content, label = false, sup = false, update }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const text =
|
||||
typeof content === 'string' ? content : strip(ReactDOMServer.renderToStaticMarkup(content))
|
||||
|
||||
const style = sup ? 'tw-w-4 tw-h-4 tw--mt-4' : 'tw-w-5 tw-h-5'
|
||||
|
||||
return (
|
||||
<Copy text={text} onCopy={() => handleCopied(setCopied, label, update)}>
|
||||
<button className={copied ? 'tw-text-success' : ''}>
|
||||
{copied ? (
|
||||
<OkIcon
|
||||
className={`${style} tw-text-success-content tw-bg-success tw-rounded-full tw-p-1`}
|
||||
stroke={4}
|
||||
/>
|
||||
) : (
|
||||
<CopyIcon className={`${style} tw-text-inherit`} />
|
||||
)}
|
||||
</button>
|
||||
</Copy>
|
||||
)
|
||||
}
|
||||
|
||||
export const CopyToClipboardButton = ({ content, label = false, update, children }) => {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const text =
|
||||
typeof content === 'string' ? content : strip(ReactDOMServer.renderToStaticMarkup(content))
|
||||
|
||||
const style = 'tw-w-6 tw-h-6'
|
||||
|
||||
return (
|
||||
<Copy text={text} onCopy={() => handleCopied(setCopied, label, update)}>
|
||||
<button
|
||||
className={`${horFlexClasses} tw-daisy-btn ${copied ? 'tw-daisy-btn-success' : 'tw-daisy-btn-primary'}`}
|
||||
>
|
||||
{copied ? (
|
||||
<OkIcon
|
||||
className={`${style} tw-text-success-content tw-bg-success tw-rounded-full tw-p-1`}
|
||||
stroke={4}
|
||||
/>
|
||||
) : (
|
||||
<CopyIcon className={`${style} tw-text-inherit`} />
|
||||
)}
|
||||
<div>{children}</div>
|
||||
</button>
|
||||
</Copy>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,232 @@
|
|||
// Dependencies
|
||||
import { linkClasses, horFlexClasses, patternUrlFromState } from '@freesewing/utils'
|
||||
import { exportTypes, handleExport } from '../../lib/export/index.mjs'
|
||||
// Hooks
|
||||
import React, { useState } from 'react'
|
||||
// Components
|
||||
import { H1, H2, H3, H5 } from '@freesewing/react/components/Heading'
|
||||
import { Popout } from '@freesewing/react/components/Popout'
|
||||
import { HeaderMenu } from '../HeaderMenu.mjs'
|
||||
import { EditIcon, CodeIcon, TipIcon, PrintIcon } from '@freesewing/react/components/Icon'
|
||||
import CodeMirror from '@uiw/react-codemirror'
|
||||
|
||||
/**
|
||||
* This is the editSettings view
|
||||
*
|
||||
* @param {Object} props - All the props
|
||||
* @param {Function} props.config - The editor configuration
|
||||
* @param {Object} props.state - The editor state object
|
||||
* @param {Object} props.update - Helper object for updating the editor state
|
||||
*/
|
||||
export const EditSettingsView = (props) => {
|
||||
const [settings, setSettings] = useState(props.state.settings)
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeaderMenu state={state} {...{ config, update }} />
|
||||
<div className="tw-m-auto tw-mt-8 tw-max-w-2xl tw-px-4 tw-mb-8">
|
||||
<H1>Documenation</H1>
|
||||
<PrimedSettingsEditor {...props} {...{ runningSettings, dconf }} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the React component for the settings editor itself
|
||||
*/
|
||||
export const PrimedSettingsEditor = (props) => {
|
||||
/*
|
||||
* Destructure props
|
||||
*/
|
||||
const { runningSettings } = props
|
||||
|
||||
/*
|
||||
* React state
|
||||
*/
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const [mSettings, update, setMSettings] = useStateObject(runningSettings) // Holds the settings
|
||||
const [validationReport, setValidationReport] = useState(false) // Holds the validatino report
|
||||
const [showDelta, setShowDelta] = useState(false)
|
||||
const [deployOngoing, setDeployOngoing] = useState(false)
|
||||
const [doValidate, setDoValidate] = useState(false)
|
||||
const [kiosk, setKiosk] = useState(false)
|
||||
const [localJson, setLocalJson] = useState(JSON.stringify(runningSettings, null, 2)) // Holds the settings as JSON
|
||||
const [localYaml, setLocalYaml] = useState(yaml.stringify(runningSettings)) // Holds the settings as YAML
|
||||
|
||||
/*
|
||||
* Method to revert to running settings
|
||||
*/
|
||||
const revert = () => setMSettings(cloneAsPojo(runningSettings))
|
||||
|
||||
/*
|
||||
* API client
|
||||
*/
|
||||
const { api } = useApi()
|
||||
|
||||
/*
|
||||
* Loading context
|
||||
*/
|
||||
const { setLoadingStatus } = useContext(LoadingStatusContext)
|
||||
|
||||
/*
|
||||
* Helper method to deploy the settings
|
||||
*/
|
||||
const deploy = async () => {
|
||||
setLoadingStatus([true, 'Uploading settings'])
|
||||
setDeployOngoing(true)
|
||||
const result = await api.deploy(mSettings)
|
||||
return result[1] === 204
|
||||
? setLoadingStatus([true, 'Settings updated', true, true])
|
||||
: setLoadingStatus([true, `Unable to deploy the settings`, true, false])
|
||||
}
|
||||
|
||||
if (!mSettings.cluster) return null
|
||||
|
||||
/*
|
||||
* Handle settings delta
|
||||
*/
|
||||
const delta =
|
||||
diffCheck(yaml.stringify(runningSettings), yaml.stringify(mSettings)).length > 1 ? true : false
|
||||
|
||||
if (deployOngoing)
|
||||
return (
|
||||
<>
|
||||
<Box color="success">
|
||||
<div className="flex flex-row items-center gap-2 text-success-content">
|
||||
<div className="w-6 h-6">
|
||||
<OkIcon className="w-6 h-6 text-success-content" stroke={4} />
|
||||
</div>
|
||||
Settings are being deployed
|
||||
</div>
|
||||
</Box>
|
||||
<p>Please wait as Morio applies the new settings.</p>
|
||||
</>
|
||||
)
|
||||
|
||||
const onChangeYaml = (input) => {
|
||||
let newSettings
|
||||
try {
|
||||
newSettings = yaml.parse(input)
|
||||
if (newSettings) {
|
||||
setLocalYaml(input)
|
||||
setMSettings(newSettings)
|
||||
}
|
||||
} catch (err) {
|
||||
// This is fine
|
||||
}
|
||||
}
|
||||
const onChangeJson = (input) => {
|
||||
let newSettings
|
||||
try {
|
||||
newSettings = JSON.parse(input)
|
||||
if (newSettings) {
|
||||
setLocalJson(input)
|
||||
setMSettings(newSettings)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
// This is fine
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{mSettings.preseed?.base ? (
|
||||
<Popout warning>
|
||||
<h5>These settings are preseeded</h5>
|
||||
<p>
|
||||
This Morio deployment uses preseeded settings. This means the settings are loaded from a
|
||||
remote system, typically a version control system like GitLab or GitHub.
|
||||
</p>
|
||||
<p>
|
||||
While you <b>can</b> update the settings here, those settings will be lost next time
|
||||
Morio is reseeded.
|
||||
<br />
|
||||
You probably should <b>update the preseeded setting instead</b>.
|
||||
</p>
|
||||
</Popout>
|
||||
) : null}
|
||||
{doValidate ? (
|
||||
<>
|
||||
<ShowSettingsValidation
|
||||
{...{
|
||||
api,
|
||||
deploy,
|
||||
mSettings,
|
||||
setLoadingStatus,
|
||||
setValidationReport,
|
||||
validationReport,
|
||||
}}
|
||||
/>
|
||||
<p className="text-right w-full">
|
||||
<button
|
||||
className="btn btn-primary btn-outline btn-s btn-sm"
|
||||
onClick={() => setDoValidate(false)}
|
||||
>
|
||||
<NoteIcon /> Back to editor
|
||||
</button>
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<div className={kiosk ? 'absolute top-12 left-0 w-screen h-screen z-50 bg-base-100' : ''}>
|
||||
<Tabs tabs="YAML, JSON">
|
||||
<Tab id="json" name="test" label="As YAML">
|
||||
<CodeMirror
|
||||
value={localYaml}
|
||||
height={kiosk ? '90vh' : '70vh'}
|
||||
onChange={onChangeYaml}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab id="yaml" label="As JSON">
|
||||
<CodeMirror
|
||||
value={localJson}
|
||||
height={kiosk ? '90vh' : '70vh'}
|
||||
extensions={[jsonLang()]}
|
||||
onChange={onChangeJson}
|
||||
/>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
<div className="my-2 w-full flex flex-row flex-wrap items-center gap-2 justify-center">
|
||||
<button
|
||||
className="btn btn-primary btn-outline flex flex-row items-center gap-2"
|
||||
onClick={() => setKiosk(!kiosk)}
|
||||
>
|
||||
<ExpandIcon /> {kiosk ? 'Collapse' : 'Expand'}
|
||||
</button>
|
||||
<button className="btn btn-primary" onClick={() => setDoValidate(true)}>
|
||||
Validate Settings
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!doValidate && delta ? (
|
||||
<Popout note>
|
||||
<h4>You have made changes that are yet to be deployed</h4>
|
||||
<p>The settings have been edited, and are now different from the deployed settings.</p>
|
||||
{showDelta ? (
|
||||
<div className="my-4 w-full overflow-scroll">
|
||||
<DiffViewer
|
||||
from={yaml.stringify(runningSettings)}
|
||||
to={yaml.stringify(mSettings)}
|
||||
fromTitle="Currently deployed settings"
|
||||
toTitle="Your edits"
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="flex flex-row flex-wrap gap-2 justify-end w-full">
|
||||
<button className="btn btn-warning btn-ghost" onClick={revert}>
|
||||
Revert to Running Settings
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-primary btn-outline"
|
||||
onClick={() => setShowDelta(!showDelta)}
|
||||
>
|
||||
{showDelta ? 'Hide' : 'Show'} Settings Delta
|
||||
</button>
|
||||
</div>
|
||||
</Popout>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -7,7 +7,7 @@ import React, { useState } from 'react'
|
|||
import { H1, H2, H3, H5 } from '@freesewing/react/components/Heading'
|
||||
import { Popout } from '@freesewing/react/components/Popout'
|
||||
import { HeaderMenu } from '../HeaderMenu.mjs'
|
||||
import { CopyToClipboardButton } from '../CopyToClipboard.mjs'
|
||||
import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton'
|
||||
import { Highlight } from '@freesewing/react/components/Highlight'
|
||||
import { EditIcon, CodeIcon, TipIcon, PrintIcon } from '@freesewing/react/components/Icon'
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ExportView } from './ExportView.mjs'
|
|||
import { UndosView } from './UndosView.mjs'
|
||||
import { LayoutView } from './LayoutView.mjs'
|
||||
import { DocsView } from './DocsView.mjs'
|
||||
import { EditSettingsView } from './EditSettingsView.mjs'
|
||||
import { ErrorIcon } from '@freesewing/react/components/Icon'
|
||||
import {
|
||||
OptionsIcon,
|
||||
|
@ -61,6 +62,7 @@ export const View = (props) => {
|
|||
if (view === 'undos') return <UndosView {...props} />
|
||||
if (view === 'layout') return <LayoutView {...props} />
|
||||
if (view === 'docs') return <DocsView {...props} />
|
||||
if (view === 'editSettings') return <EditSettingsView {...props} />
|
||||
|
||||
return <h1 className="tw-ext-center tw-my-12">No view component for view {props.view}</h1>
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import { CopyToClipboard } from '@freesewing/react/components/CopyToClipboard'
|
||||
import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton'
|
||||
|
||||
const defaultTitles = {
|
||||
js: 'Javascript',
|
||||
|
@ -48,7 +48,7 @@ export const Highlight = ({
|
|||
`}
|
||||
>
|
||||
<span>{label}</span>
|
||||
{noCopy ? null : <CopyToClipboard content={copy ? copy : children} label={label} />}
|
||||
{noCopy ? null : <CopyToClipboardButton content={copy ? copy : children} label={label} />}
|
||||
</div>
|
||||
<pre {...preProps}>{children}</pre>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useState, useContext } from 'react'
|
||||
import { CopyToClipboard as Copy } from 'react-copy-to-clipboard'
|
||||
import { copyToClipboard } from '@freesewing/utils'
|
||||
import { LoadingStatusContext } from '@freesewing/react/context/LoadingStatus'
|
||||
|
||||
export const KeyVal = ({
|
||||
|
@ -47,9 +47,15 @@ export const KeyVal = ({
|
|||
)
|
||||
|
||||
return onClick === false ? (
|
||||
<Copy text={val} onCopy={() => (noCopy ? null : handleCopied(setCopied, setLoadingStatus, k))}>
|
||||
<button className="tw-daisy-btn-ghost tw-p-0">{inner}</button>
|
||||
</Copy>
|
||||
<button
|
||||
className="tw-daisy-btn-ghost tw-p-0"
|
||||
onClick={() => {
|
||||
copyToClipboard(val)
|
||||
handleCopied(setCopied, setLoadingStatus, k)
|
||||
}}
|
||||
>
|
||||
{inner}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
className="tw-daisy-btn-ghost tw-p-0"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from 'react'
|
||||
import { shortUuid } from '@freesewing/utils'
|
||||
import { Link } from '@freesewing/react/components/Link'
|
||||
import { CopyToClipboard } from '@freesewing/react/components/CopyToClipboard'
|
||||
import { CopyToClipboardButton } from '@freesewing/react/components/CopyToClipboardButton'
|
||||
|
||||
/*
|
||||
* Displays a UUID, but shorter
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"./components/Button": "./components/Button/index.mjs",
|
||||
"./components/Collection": "./components/Collection/index.mjs",
|
||||
"./components/Control": "./components/Control/index.mjs",
|
||||
"./components/CopyToClipboard": "./components/CopyToClipboard/index.mjs",
|
||||
"./components/CopyToClipboardButton": "./components/CopyToClipboardButton/index.mjs",
|
||||
"./components/Design": "./components/Design/index.mjs",
|
||||
"./components/Docusaurus": "./components/Docusaurus/index.mjs",
|
||||
"./components/Editor": "./components/Editor/index.mjs",
|
||||
|
@ -79,18 +79,24 @@
|
|||
"prettier": "npx prettier --write 'components/**/*.mjs' 'hooks/**/*.mjs' 'lib/**/*.mjs' 'context/**/*.mjs' 'config/**/*.mjs'"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0"
|
||||
"react": "^19.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "1.7.2",
|
||||
"highlight.js": "^11.11.0",
|
||||
"html-react-parser": "^5.0.7",
|
||||
"@uiw/react-codemirror": "^4.23.8",
|
||||
"d3-drag": "3.0.0",
|
||||
"d3-selection": "3.0.0",
|
||||
"file-saver": "^2.0.5",
|
||||
"highlight.js": "^11.11.1",
|
||||
"html-react-parser": "^5.2.2",
|
||||
"jotai": "^2.12.1",
|
||||
"jotai-location": "^0.5.5",
|
||||
"luxon": "^3.5.0",
|
||||
"nuqs": "^1.17.6",
|
||||
"react-markdown": "^9.0.1",
|
||||
"tlds": "^1.255.0",
|
||||
"use-local-storage-state": "19.1.0",
|
||||
"use-session-storage-state": "^19.0.0"
|
||||
"pdfkit": "^0.16.0",
|
||||
"react-dropzone": "^14.3.5",
|
||||
"react-zoom-pan-pinch": "^3.7.0",
|
||||
"svg-to-pdfkit": "^0.1.8",
|
||||
"use-local-storage-state": "^19.5.0",
|
||||
"web-worker": "^1.5.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"files": [
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Change log for: rehype-highlight-lines
|
||||
|
||||
|
||||
## 3.0.0 (2023-09-30)
|
||||
|
||||
### Changed
|
||||
|
||||
- All FreeSewing packages are now ESM only.
|
||||
- All FreeSewing packages now use named exports.
|
||||
- Dropped support for NodeJS 14. NodeJS 18 (LTS/hydrogen) or more recent is now required.
|
||||
|
||||
|
||||
This is the **initial release**, and the start of this change log.
|
||||
|
||||
> Prior to version 2, FreeSewing was not a JavaScript project.
|
||||
> As such, that history is out of scope for this change log.
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
<p align='center'><a
|
||||
href="https://www.npmjs.com/package/rehype-highlight-lines"
|
||||
title="rehype-highlight-lines on NPM"
|
||||
><img src="https://img.shields.io/npm/v/rehype-highlight-lines.svg"
|
||||
alt="rehype-highlight-lines on NPM"/>
|
||||
</a><a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img src="https://img.shields.io/npm/l/rehype-highlight-lines.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a><a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="Code quality on DeepScan"/>
|
||||
</a><a
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Arehype-highlight-lines"
|
||||
title="Open issues tagged pkg:rehype-highlight-lines"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing/pkg:rehype-highlight-lines.svg?label=Issues"
|
||||
alt="Open issues tagged pkg:rehype-highlight-lines"/>
|
||||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img src="https://img.shields.io/badge/all_contributors-131-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p><p align='center'><a
|
||||
href="https://twitter.com/freesewing_org"
|
||||
title="Follow @freesewing_org on Twitter"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-blue.svg?logo=twitter&logoColor=white&logoWidth=15"
|
||||
alt="Follow @freesewing_org on Twitter"/>
|
||||
</a><a
|
||||
href="https://chat.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"/>
|
||||
</a><a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"/>
|
||||
</a><a
|
||||
href="https://instagram.com/freesewing_org"
|
||||
title="Follow @freesewing_org on Twitter"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-E4405F.svg?logo=instagram&logoColor=white&logoWidth=15"
|
||||
alt="Follow @freesewing_org on Twitter"/>
|
||||
</a></p>
|
||||
|
||||
# rehype-highlight-lines
|
||||
|
||||
A Rehype plugin to add highlighted lines to code blocks
|
||||
|
||||
|
||||
|
||||
# FreeSewing
|
||||
|
||||
> [!TIP]
|
||||
>#### Support FreeSewing: Become a patron, or make a one-time donation 🥰
|
||||
>
|
||||
> FreeSewing is an open source project maintained by Joost De Cock and financially supported by the FreeSewing patrons.
|
||||
>
|
||||
> If you feel FreeSewing is worthwhile, and you can spend a few coins without
|
||||
hardship, then you should [join us and become a patron](https://freesewing.org/community/join).
|
||||
|
||||
## What am I looking at? 🤔
|
||||
|
||||
This repository is the FreeSewing *monorepo* holding all FreeSewing's websites, documentation, designs, plugins, and other NPM packages.
|
||||
|
||||
This folder holds: rehype-highlight-lines
|
||||
|
||||
If you're not entirely sure what to do or how to start, type this command:
|
||||
|
||||
```
|
||||
npm run tips
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you don't want to set up a dev environment, you can run it in your browser:
|
||||
>
|
||||
> [](https://gitpod.io/#https://github.com/freesewing/freesewing)
|
||||
>
|
||||
> We recommend that you fork our repository and then
|
||||
> put `gitpod.io/#<entire-url-of-your-fork` into a browser
|
||||
> to start up a browser-based dev environment of your own.
|
||||
|
||||
## About FreeSewing 💀
|
||||
|
||||
Where the world of makers and developers collide, that's where you'll find FreeSewing.
|
||||
|
||||
If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate
|
||||
sewing patterns adapted to your measurements.
|
||||
|
||||
If you're a developer, the FreeSewing documentation lives at [freesewing.dev](https://freesewing.dev/).
|
||||
The FreeSewing [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox
|
||||
for parametric design of sewing patterns. But FreeSewing also provides a range
|
||||
of [plugins](https://freesewing.dev/reference/plugins/) that further extend the
|
||||
functionality of the platform.
|
||||
|
||||
If you have NodeJS installed, you can try it right now by running:
|
||||
|
||||
```bash
|
||||
npx @freesewing/new-design
|
||||
```
|
||||
|
||||
Getting started guides are available for:
|
||||
- [Linux](https://freesewing.dev/tutorials/getting-started-linux/)
|
||||
- [MacOS](https://freesewing.dev/tutorials/getting-started-mac/)
|
||||
- [Windows](https://freesewing.dev/tutorials/getting-started-windows/)
|
||||
|
||||
The [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) will
|
||||
show you how to create your first parametric design.
|
||||
|
||||
## Getting started ⚡
|
||||
|
||||
To get started with FreeSewing, you can spin up our development environment with:
|
||||
|
||||
```bash
|
||||
npx @freesewing/new-design
|
||||
```
|
||||
|
||||
To work with FreeSewing's monorepo, you'll need [NodeJS v20](https://nodejs.org) on your system.
|
||||
Once you have that, clone (or fork) this repo and run `npm run kickstart`:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:freesewing/freesewing.git
|
||||
cd freesewing
|
||||
npm run kickstart
|
||||
```
|
||||
|
||||
## Links 👩💻
|
||||
|
||||
**Official channels**
|
||||
|
||||
- 💻 Makers website: [FreeSewing.org](https://freesewing.org)
|
||||
- 💻 Developers website: [FreeSewing.dev](https://freesewing.dev)
|
||||
- ✅ [Support](https://github.com/freesewing/freesewing/issues/new/choose),
|
||||
[Issues](https://github.com/freesewing/freesewing/issues) &
|
||||
[Discussions](https://github.com/freesewing/freesewing/discussions) on
|
||||
[GitHub](https://github.com/freesewing/freesewing)
|
||||
|
||||
**Social media**
|
||||
|
||||
- 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org)
|
||||
- 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org)
|
||||
|
||||
**Places the FreeSewing community hangs out**
|
||||
|
||||
- 💬 [Discord](https://discord.freesewing.org/)
|
||||
- 💬 [Facebook](https://www.facebook.com/groups/627769821272714/)
|
||||
- 💬 [Reddit](https://www.reddit.com/r/freesewing/)
|
||||
|
||||
## License: MIT 🤓
|
||||
|
||||
© [Joost De Cock](https://github.com/joostdecock).
|
||||
See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details.
|
||||
|
||||
## Where to get help 🤯
|
||||
|
||||
For [Support](https://github.com/freesewing/freesewing/issues/new/choose),
|
||||
please use the [Issues](https://github.com/freesewing/freesewing/issues) &
|
||||
[Discussions](https://github.com/freesewing/freesewing/discussions) on
|
||||
[GitHub](https://github.com/freesewing/freesewing).
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// This file is auto-generated | All changes you make will be overwritten.
|
||||
export const name = 'rehype-highlight-lines'
|
||||
export const version = '3.3.0-rc.1'
|
||||
export const data = { name, version }
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"name": "rehype-highlight-lines",
|
||||
"version": "3.3.0-rc.1",
|
||||
"description": "A Rehype plugin to add highlighted lines to code blocks",
|
||||
"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",
|
||||
"freesewing"
|
||||
],
|
||||
"type": "module",
|
||||
"module": "src/index.mjs",
|
||||
"exports": {
|
||||
".": "./src/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -",
|
||||
"test": "echo \"rehype-highlight-lines: No tests configured. Perhaps you could write some?\" && exit 0",
|
||||
"tips": "node ../../scripts/help.mjs",
|
||||
"lint": "npx eslint 'src/*.mjs'"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"dependencies": {
|
||||
"unist-util-remove": "4.0.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"files": [
|
||||
"src/**",
|
||||
"README.md"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"tag": "next"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
import { visit } from 'unist-util-visit'
|
||||
import { remove } from 'unist-util-remove'
|
||||
|
||||
const dflts = {
|
||||
commentTag: 'span',
|
||||
commentClass: 'hljs-comment',
|
||||
openingCommentHighlight: 'highlight-start',
|
||||
closingCommentHighlight: 'highlight-end',
|
||||
openingCommentStrikeout: 'strikeout-start',
|
||||
closingCommentStrikeout: 'strikeout-end',
|
||||
highlightTag: 'section',
|
||||
highlightClass: 'highlight-lines',
|
||||
strikeoutClass: 'strikeout-lines',
|
||||
swallow: true,
|
||||
}
|
||||
|
||||
export default (userOptions = {}) => {
|
||||
// Merge defaults with user-supplied options
|
||||
const options = {
|
||||
...dflts,
|
||||
...userOptions,
|
||||
}
|
||||
|
||||
const splitParams = (node) => {
|
||||
if (node.children.length === 1 && node.children[0].type === 'text') {
|
||||
const content = node.children[0].value.split('\n')
|
||||
node.children = content.map((value) =>
|
||||
value.includes('//')
|
||||
? {
|
||||
type: 'element',
|
||||
tagName: 'span',
|
||||
properties: {
|
||||
className: options.commentClass,
|
||||
},
|
||||
children: [{ type: 'text', value }],
|
||||
}
|
||||
: { type: 'text', value: value + '\n', isParamLine: true }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of whether we've opened a highlight block
|
||||
let isOpen = 0
|
||||
let children = {}
|
||||
|
||||
// Detect opening or closing comment
|
||||
const isOpeningOrClosingComment = (node) => {
|
||||
if (
|
||||
node &&
|
||||
node.tagName === options.commentTag &&
|
||||
node.properties?.className.includes(options.commentClass)
|
||||
) {
|
||||
if (node.children[0].value.includes(options.openingCommentHighlight))
|
||||
return ['opening', 'highlight']
|
||||
if (node.children[0].value.includes(options.closingCommentHighlight))
|
||||
return ['closing', 'highlight']
|
||||
if (node.children[0].value.includes(options.openingCommentStrikeout))
|
||||
return ['opening', 'strikeout']
|
||||
if (node.children[0].value.includes(options.closingCommentStrikeout))
|
||||
return ['closing', 'strikeout']
|
||||
}
|
||||
|
||||
return [false, 'highlight']
|
||||
}
|
||||
|
||||
// Visitor method
|
||||
const visitor = (node, i, parent) => {
|
||||
const [type, variant] = isOpeningOrClosingComment(node)
|
||||
if (type) {
|
||||
if (type === 'opening') {
|
||||
isOpen = 1
|
||||
|
||||
// Deal with extra linebreaks in the element before the start
|
||||
const prev = parent.children[i - 1]
|
||||
if (prev?.type === 'text' && prev.value.includes('\n'))
|
||||
prev.value = prev.value.replace(/\n/g, '') + '\n'
|
||||
|
||||
if (options.swallow) node.__remove_dupes = true
|
||||
} else if (type === 'closing') {
|
||||
// Deal with extra linebreaks in the element before the end
|
||||
const prev = children[i - 1]
|
||||
if (prev.type === 'text' && prev.value.includes('\n') && !node.isParamLine)
|
||||
prev.value = prev.value.trimEnd()
|
||||
|
||||
isOpen = 0
|
||||
const curNode = { ...node }
|
||||
parent.children[i] = {
|
||||
type: 'element',
|
||||
tagName: options.highlightTag,
|
||||
properties: {
|
||||
className: Array.isArray(options[`${variant}Class`])
|
||||
? options[`${variant}Class`]
|
||||
: [options[`${variant}Class`]],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['code-section-inner'],
|
||||
},
|
||||
children: [...Object.values(children)],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
if (!options.swallow) parent[i].children.push(curNode)
|
||||
children = {}
|
||||
}
|
||||
} else if (isOpen) {
|
||||
if (
|
||||
parent.tagName === 'code' ||
|
||||
(parent.tagName === 'span' &&
|
||||
parent.properties?.className &&
|
||||
parent.properties.className.includes('hljs-params'))
|
||||
) {
|
||||
if (node.type === 'text' && node.value === '\n') {
|
||||
// Linebreak
|
||||
node.type = 'element'
|
||||
node.tagName = 'span'
|
||||
node.children = [
|
||||
{
|
||||
type: 'text',
|
||||
value: '\n',
|
||||
},
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'span',
|
||||
properties: {
|
||||
className: ['code-line-break'],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
// On the first highlighted line, trim the previous linebreak (not for param lines)
|
||||
if (isOpen === 1 && node.type === 'text' && !node.isParamLine)
|
||||
node.value = node.value.replace('\n', '')
|
||||
children[i] = { ...node }
|
||||
isOpen++
|
||||
node.__remove_dupes = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isParamsNode = (node) =>
|
||||
node?.properties?.className && node.properties.className.includes('hljs-params')
|
||||
|
||||
const transform = (tree) => {
|
||||
visit(tree, (node) => isParamsNode(node), splitParams)
|
||||
visit(tree, () => true, visitor)
|
||||
remove(tree, (node) => node.__remove_dupes === true)
|
||||
}
|
||||
|
||||
return transform
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
# Change log for: rehype-jargon
|
||||
|
||||
|
||||
## 3.0.0 (2023-09-30)
|
||||
|
||||
### Changed
|
||||
|
||||
- All FreeSewing packages are now ESM only.
|
||||
- All FreeSewing packages now use named exports.
|
||||
- Dropped support for NodeJS 14. NodeJS 18 (LTS/hydrogen) or more recent is now required.
|
||||
|
||||
|
||||
This is the **initial release**, and the start of this change log.
|
||||
|
||||
> Prior to version 2, FreeSewing was not a JavaScript project.
|
||||
> As such, that history is out of scope for this change log.
|
||||
|
|
@ -1,288 +0,0 @@
|
|||
<p align='center'><a
|
||||
href="https://www.npmjs.com/package/rehype-jargon"
|
||||
title="rehype-jargon on NPM"
|
||||
><img src="https://img.shields.io/npm/v/rehype-jargon.svg"
|
||||
alt="rehype-jargon on NPM"/>
|
||||
</a><a
|
||||
href="https://opensource.org/licenses/MIT"
|
||||
title="License: MIT"
|
||||
><img src="https://img.shields.io/npm/l/rehype-jargon.svg?label=License"
|
||||
alt="License: MIT"/>
|
||||
</a><a
|
||||
href="https://deepscan.io/dashboard#view=project&tid=2114&pid=2993&bid=23256"
|
||||
title="Code quality on DeepScan"
|
||||
><img src="https://deepscan.io/api/teams/2114/projects/2993/branches/23256/badge/grade.svg"
|
||||
alt="Code quality on DeepScan"/>
|
||||
</a><a
|
||||
href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Arehype-jargon"
|
||||
title="Open issues tagged pkg:rehype-jargon"
|
||||
><img src="https://img.shields.io/github/issues/freesewing/freesewing/pkg:rehype-jargon.svg?label=Issues"
|
||||
alt="Open issues tagged pkg:rehype-jargon"/>
|
||||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img src="https://img.shields.io/badge/all_contributors-131-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p><p align='center'><a
|
||||
href="https://twitter.com/freesewing_org"
|
||||
title="Follow @freesewing_org on Twitter"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-blue.svg?logo=twitter&logoColor=white&logoWidth=15"
|
||||
alt="Follow @freesewing_org on Twitter"/>
|
||||
</a><a
|
||||
href="https://chat.freesewing.org"
|
||||
title="Chat with us on Discord"
|
||||
><img src="https://img.shields.io/discord/698854858052075530?label=Chat%20on%20Discord"
|
||||
alt="Chat with us on Discord"/>
|
||||
</a><a
|
||||
href="https://freesewing.org/patrons/join"
|
||||
title="Become a FreeSewing Patron"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Support%20us-blueviolet.svg?logo=cash-app&logoColor=white&logoWidth=15"
|
||||
alt="Become a FreeSewing Patron"/>
|
||||
</a><a
|
||||
href="https://instagram.com/freesewing_org"
|
||||
title="Follow @freesewing_org on Twitter"
|
||||
><img src="https://img.shields.io/badge/%F3%A0%80%A0-Follow%20us-E4405F.svg?logo=instagram&logoColor=white&logoWidth=15"
|
||||
alt="Follow @freesewing_org on Twitter"/>
|
||||
</a></p>
|
||||
|
||||
# rehype-jargon
|
||||
|
||||
A Rehype plugin for jargon terms
|
||||
|
||||
## About
|
||||
|
||||
This [Rehype](https://github.com/rehypejs/rehype) plugin allows you to use _jargon_ in your
|
||||
markdown/mdx/html content and use a centrally managed file of jargon terms and their definitions.
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
To install this plugin, run:
|
||||
|
||||
```
|
||||
npm install --save rehype-jargon
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
> **Tip**: See https://github.com/joostdecock/rehype-jargon-example for a minimal repository that uses this plugin
|
||||
|
||||
### Create your jargon file
|
||||
|
||||
This plugin requires a _jargon file_ with terms defenitions. For example:
|
||||
|
||||
```js
|
||||
export const jargon = {
|
||||
rehype: "<b>rehype</b> is a tool that transforms HTML with plugins. These plugins can inspect and change the HTML. You can use rehype on the server, the client, CLIs, deno, etc.",
|
||||
freesewing: "<b>FreeSewing</b> is an open source platform for made-to-measure sewing patterns. See <a href='https://freesewing.org/'>freesewing.org</a>"
|
||||
}
|
||||
```
|
||||
|
||||
### Import the plugin
|
||||
|
||||
Now import the plugin, and pass it your jargon:
|
||||
|
||||
```js
|
||||
var remark = require('remark')
|
||||
var html = require('remark-html')
|
||||
var plugin = require('remark-jargon')
|
||||
var jargon = require('./jargon.js')
|
||||
|
||||
remark()
|
||||
.use(html)
|
||||
.use(plugin, { jargon: jargon })
|
||||
.process('This is a plugin for _remark_ originally written for _freesewing_.', function (err, file) {
|
||||
console.log(String(file))
|
||||
})
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This plugin will only add markup to your jargon if you _emphasize_ it.
|
||||
|
||||
|
||||
### Style your jargon
|
||||
|
||||
You will need to add CSS to style your jargon properly, and hide the definition by default.
|
||||
Below is an example to get you started:
|
||||
|
||||
```css
|
||||
// Add a dashed line under jargon terms
|
||||
.jargon-term {
|
||||
text-decoration: underline dotted #228be6
|
||||
}
|
||||
// Add a question mark behind/above jargon terms
|
||||
.jargon-term::after {
|
||||
content: "?";
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
transform: translate(0, -0.5em);
|
||||
font-size: 75%;
|
||||
color: #228be6;
|
||||
margin-left: 3px;
|
||||
}
|
||||
// Hover behavior for the therm itself
|
||||
.jargon-term:hover {
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
cursor: help;
|
||||
}
|
||||
// Hide info by default
|
||||
.jargon-term .jargon-info {
|
||||
display: none
|
||||
}
|
||||
// Show info on hover
|
||||
.jargon-term:hover .jargon-info {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 1.5em;
|
||||
left: 0;
|
||||
background: #F8F8F8;
|
||||
border: 1px solid #DCDCDC;
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
font-size: 90%;
|
||||
min-width: 250px;
|
||||
max-width: 450px;
|
||||
z-index: 1;
|
||||
}
|
||||
```
|
||||
|
||||
## Tips for using jargon
|
||||
|
||||
### Lowercase your terms in the jargon file
|
||||
|
||||
When looking for terms to match, we lowercase the term your emphazised.
|
||||
So in the jargon file, you should use `msf`, but in your text, you can use `MSF`, `Msf`, or `msf`.
|
||||
|
||||
### If you use HTML, only use inline elements
|
||||
|
||||
Your jargon term definition can contain HTML, but only inline elements.
|
||||
Typically, you will want to stick to:
|
||||
|
||||
- Making things **bold**
|
||||
- Inserting [links](#)
|
||||
|
||||
## Getting help
|
||||
|
||||
This plugin is written by/for [FreeSewing](https://github.com/freesewing).
|
||||
For help or feedback, please stop by [the FreeSewing chat room](https://gitter.im/freesewing/development) or
|
||||
[create an issue](https://github.com/freesewing/freesewing/issues/new).
|
||||
|
||||
|
||||
## Use with Gatsby
|
||||
|
||||
Please see [gatsby-remark-jargon](https://github.com/freesewing/freesewing/tree/develop/packages/gatsby-remark-jargon) for
|
||||
info and instructions on how to use this plugin with [Gatsby](https://www.gatsbyjs.org/).
|
||||
|
||||
|
||||
# FreeSewing
|
||||
|
||||
> [!TIP]
|
||||
>#### Support FreeSewing: Become a patron, or make a one-time donation 🥰
|
||||
>
|
||||
> FreeSewing is an open source project maintained by Joost De Cock and financially supported by the FreeSewing patrons.
|
||||
>
|
||||
> If you feel FreeSewing is worthwhile, and you can spend a few coins without
|
||||
hardship, then you should [join us and become a patron](https://freesewing.org/community/join).
|
||||
|
||||
## What am I looking at? 🤔
|
||||
|
||||
This repository is the FreeSewing *monorepo* holding all FreeSewing's websites, documentation, designs, plugins, and other NPM packages.
|
||||
|
||||
This folder holds: rehype-jargon
|
||||
|
||||
If you're not entirely sure what to do or how to start, type this command:
|
||||
|
||||
```
|
||||
npm run tips
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you don't want to set up a dev environment, you can run it in your browser:
|
||||
>
|
||||
> [](https://gitpod.io/#https://github.com/freesewing/freesewing)
|
||||
>
|
||||
> We recommend that you fork our repository and then
|
||||
> put `gitpod.io/#<entire-url-of-your-fork` into a browser
|
||||
> to start up a browser-based dev environment of your own.
|
||||
|
||||
## About FreeSewing 💀
|
||||
|
||||
Where the world of makers and developers collide, that's where you'll find FreeSewing.
|
||||
|
||||
If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate
|
||||
sewing patterns adapted to your measurements.
|
||||
|
||||
If you're a developer, the FreeSewing documentation lives at [freesewing.dev](https://freesewing.dev/).
|
||||
The FreeSewing [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox
|
||||
for parametric design of sewing patterns. But FreeSewing also provides a range
|
||||
of [plugins](https://freesewing.dev/reference/plugins/) that further extend the
|
||||
functionality of the platform.
|
||||
|
||||
If you have NodeJS installed, you can try it right now by running:
|
||||
|
||||
```bash
|
||||
npx @freesewing/new-design
|
||||
```
|
||||
|
||||
Getting started guides are available for:
|
||||
- [Linux](https://freesewing.dev/tutorials/getting-started-linux/)
|
||||
- [MacOS](https://freesewing.dev/tutorials/getting-started-mac/)
|
||||
- [Windows](https://freesewing.dev/tutorials/getting-started-windows/)
|
||||
|
||||
The [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) will
|
||||
show you how to create your first parametric design.
|
||||
|
||||
## Getting started ⚡
|
||||
|
||||
To get started with FreeSewing, you can spin up our development environment with:
|
||||
|
||||
```bash
|
||||
npx @freesewing/new-design
|
||||
```
|
||||
|
||||
To work with FreeSewing's monorepo, you'll need [NodeJS v20](https://nodejs.org) on your system.
|
||||
Once you have that, clone (or fork) this repo and run `npm run kickstart`:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:freesewing/freesewing.git
|
||||
cd freesewing
|
||||
npm run kickstart
|
||||
```
|
||||
|
||||
## Links 👩💻
|
||||
|
||||
**Official channels**
|
||||
|
||||
- 💻 Makers website: [FreeSewing.org](https://freesewing.org)
|
||||
- 💻 Developers website: [FreeSewing.dev](https://freesewing.dev)
|
||||
- ✅ [Support](https://github.com/freesewing/freesewing/issues/new/choose),
|
||||
[Issues](https://github.com/freesewing/freesewing/issues) &
|
||||
[Discussions](https://github.com/freesewing/freesewing/discussions) on
|
||||
[GitHub](https://github.com/freesewing/freesewing)
|
||||
|
||||
**Social media**
|
||||
|
||||
- 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org)
|
||||
- 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org)
|
||||
|
||||
**Places the FreeSewing community hangs out**
|
||||
|
||||
- 💬 [Discord](https://discord.freesewing.org/)
|
||||
- 💬 [Facebook](https://www.facebook.com/groups/627769821272714/)
|
||||
- 💬 [Reddit](https://www.reddit.com/r/freesewing/)
|
||||
|
||||
## License: MIT 🤓
|
||||
|
||||
© [Joost De Cock](https://github.com/joostdecock).
|
||||
See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details.
|
||||
|
||||
## Where to get help 🤯
|
||||
|
||||
For [Support](https://github.com/freesewing/freesewing/issues/new/choose),
|
||||
please use the [Issues](https://github.com/freesewing/freesewing/issues) &
|
||||
[Discussions](https://github.com/freesewing/freesewing/discussions) on
|
||||
[GitHub](https://github.com/freesewing/freesewing).
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
// This file is auto-generated | All changes you make will be overwritten.
|
||||
export const name = 'rehype-jargon'
|
||||
export const version = '3.3.0-rc.1'
|
||||
export const data = { name, version }
|
Binary file not shown.
Before Width: | Height: | Size: 56 KiB |
|
@ -1,126 +0,0 @@
|
|||
## About
|
||||
|
||||
This [Rehype](https://github.com/rehypejs/rehype) plugin allows you to use _jargon_ in your
|
||||
markdown/mdx/html content and use a centrally managed file of jargon terms and their definitions.
|
||||
|
||||

|
||||
|
||||
## Install
|
||||
|
||||
To install this plugin, run:
|
||||
|
||||
```
|
||||
npm install --save rehype-jargon
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
> **Tip**: See https://github.com/joostdecock/rehype-jargon-example for a minimal repository that uses this plugin
|
||||
|
||||
### Create your jargon file
|
||||
|
||||
This plugin requires a _jargon file_ with terms defenitions. For example:
|
||||
|
||||
```js
|
||||
export const jargon = {
|
||||
rehype: "<b>rehype</b> is a tool that transforms HTML with plugins. These plugins can inspect and change the HTML. You can use rehype on the server, the client, CLIs, deno, etc.",
|
||||
freesewing: "<b>FreeSewing</b> is an open source platform for made-to-measure sewing patterns. See <a href='https://freesewing.org/'>freesewing.org</a>"
|
||||
}
|
||||
```
|
||||
|
||||
### Import the plugin
|
||||
|
||||
Now import the plugin, and pass it your jargon:
|
||||
|
||||
```js
|
||||
var remark = require('remark')
|
||||
var html = require('remark-html')
|
||||
var plugin = require('remark-jargon')
|
||||
var jargon = require('./jargon.js')
|
||||
|
||||
remark()
|
||||
.use(html)
|
||||
.use(plugin, { jargon: jargon })
|
||||
.process('This is a plugin for _remark_ originally written for _freesewing_.', function (err, file) {
|
||||
console.log(String(file))
|
||||
})
|
||||
```
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> This plugin will only add markup to your jargon if you _emphasize_ it.
|
||||
|
||||
|
||||
### Style your jargon
|
||||
|
||||
You will need to add CSS to style your jargon properly, and hide the definition by default.
|
||||
Below is an example to get you started:
|
||||
|
||||
```css
|
||||
// Add a dashed line under jargon terms
|
||||
.jargon-term {
|
||||
text-decoration: underline dotted #228be6
|
||||
}
|
||||
// Add a question mark behind/above jargon terms
|
||||
.jargon-term::after {
|
||||
content: "?";
|
||||
font-weight: bold;
|
||||
display: inline-block;
|
||||
transform: translate(0, -0.5em);
|
||||
font-size: 75%;
|
||||
color: #228be6;
|
||||
margin-left: 3px;
|
||||
}
|
||||
// Hover behavior for the therm itself
|
||||
.jargon-term:hover {
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
cursor: help;
|
||||
}
|
||||
// Hide info by default
|
||||
.jargon-term .jargon-info {
|
||||
display: none
|
||||
}
|
||||
// Show info on hover
|
||||
.jargon-term:hover .jargon-info {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 1.5em;
|
||||
left: 0;
|
||||
background: #F8F8F8;
|
||||
border: 1px solid #DCDCDC;
|
||||
padding: 1rem;
|
||||
border-radius: 4px;
|
||||
font-size: 90%;
|
||||
min-width: 250px;
|
||||
max-width: 450px;
|
||||
z-index: 1;
|
||||
}
|
||||
```
|
||||
|
||||
## Tips for using jargon
|
||||
|
||||
### Lowercase your terms in the jargon file
|
||||
|
||||
When looking for terms to match, we lowercase the term your emphazised.
|
||||
So in the jargon file, you should use `msf`, but in your text, you can use `MSF`, `Msf`, or `msf`.
|
||||
|
||||
### If you use HTML, only use inline elements
|
||||
|
||||
Your jargon term definition can contain HTML, but only inline elements.
|
||||
Typically, you will want to stick to:
|
||||
|
||||
- Making things **bold**
|
||||
- Inserting [links](#)
|
||||
|
||||
## Getting help
|
||||
|
||||
This plugin is written by/for [FreeSewing](https://github.com/freesewing).
|
||||
For help or feedback, please stop by [the FreeSewing chat room](https://gitter.im/freesewing/development) or
|
||||
[create an issue](https://github.com/freesewing/freesewing/issues/new).
|
||||
|
||||
|
||||
## Use with Gatsby
|
||||
|
||||
Please see [gatsby-remark-jargon](https://github.com/freesewing/freesewing/tree/develop/packages/gatsby-remark-jargon) for
|
||||
info and instructions on how to use this plugin with [Gatsby](https://www.gatsbyjs.org/).
|
|
@ -1,48 +0,0 @@
|
|||
{
|
||||
"name": "rehype-jargon",
|
||||
"version": "3.3.0-rc.1",
|
||||
"description": "A Rehype plugin for jargon terms",
|
||||
"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",
|
||||
"freesewing"
|
||||
],
|
||||
"type": "module",
|
||||
"module": "src/index.mjs",
|
||||
"exports": {
|
||||
".": "./src/index.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -",
|
||||
"test": "echo \"rehype-jargon: No tests configured. Perhaps you could write some?\" && exit 0",
|
||||
"tips": "node ../../scripts/help.mjs",
|
||||
"lint": "npx eslint 'src/*.mjs'"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"dependencies": {
|
||||
"unist-util-visit": "5.0.0",
|
||||
"hast-util-from-html": "2.0.1"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"files": [
|
||||
"src/**",
|
||||
"README.md"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public",
|
||||
"tag": "next"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
import { visit } from 'unist-util-visit'
|
||||
import { fromHtml } from 'hast-util-from-html'
|
||||
|
||||
const jargonTransform = (term, html) =>
|
||||
`<span class="jargon-term">${term}<span class="jargon-info">${html}</span></span>`
|
||||
|
||||
export default (options) => {
|
||||
// Don't bother if we don't have any jargon
|
||||
if (!options || !options.jargon) {
|
||||
throw Error('Required "jargon" option is missing in remark-jargon configuration')
|
||||
}
|
||||
|
||||
// Allow passing in a custom transform method
|
||||
if (!options.transform) options.transform = jargonTransform
|
||||
|
||||
// Detect jargon nodes
|
||||
const isJargon = (node) => {
|
||||
if (
|
||||
node.tagName === 'em' &&
|
||||
node.children.every((n) => n.type === 'text') &&
|
||||
Object.keys(options.jargon).indexOf(node.children[0].value.toLowerCase()) !== -1
|
||||
)
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
// Visitor method
|
||||
const visitor = (node) => {
|
||||
if (isJargon(node)) {
|
||||
const termTree = fromHtml(
|
||||
options.transform(
|
||||
node.children[0].value,
|
||||
options.jargon[node.children[0].value.toLowerCase()]
|
||||
),
|
||||
{ fragment: true }
|
||||
)
|
||||
node.children = termTree.children
|
||||
}
|
||||
}
|
||||
|
||||
const transform = (tree) => {
|
||||
visit(tree, 'element', visitor)
|
||||
}
|
||||
|
||||
return transform
|
||||
}
|
|
@ -26,7 +26,10 @@
|
|||
"lint": "npx eslint 'src/**' 'tests/*.mjs'"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"tlds": "^1.255.0"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"files": [
|
||||
"src/**",
|
||||
|
|
|
@ -569,3 +569,41 @@ export function validateTld(email) {
|
|||
if (tlds.indexOf(tld) === -1) return tld
|
||||
else return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a string to the clipboard using the clipboard API
|
||||
*
|
||||
* @param {string} text - The text to copy to the clipboard
|
||||
*/
|
||||
export function copyToClipboard(text) {
|
||||
const textToCopy = text
|
||||
|
||||
/*
|
||||
* This is only available in a secure browser context
|
||||
* So when we are running a localhost dev instance,
|
||||
* this won't work, and we fall back to the one further down.
|
||||
*/
|
||||
if (navigator?.clipboard) {
|
||||
navigator.clipboard.writeText(text).catch((error) => {
|
||||
console.error('Failed to use the clipboard API to copy text to clipboard:', error)
|
||||
copyToClipboardFallback(text)
|
||||
})
|
||||
} else {
|
||||
copyToClipboardFallback(text)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies a string to the clipboard using DOM manipulation
|
||||
*
|
||||
* @param {string} text - The text to copy to the clipboard
|
||||
*/
|
||||
function copyToClipboardFallback(text) {
|
||||
const textarea = document.createElement('textarea')
|
||||
textarea.value = text
|
||||
textarea.style.position = 'fixed'
|
||||
document.body.appendChild(textarea)
|
||||
textarea.select()
|
||||
document.execCommand('copy')
|
||||
document.body.removeChild(textarea)
|
||||
}
|
||||
|
|
|
@ -14,20 +14,20 @@
|
|||
"write-heading-ids": "docusaurus write-heading-ids"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.5.2",
|
||||
"@docusaurus/preset-classic": "3.5.2",
|
||||
"@docusaurus/core": "3.7.0",
|
||||
"@docusaurus/preset-classic": "3.7.0",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"tailwindcss": "^3.4.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-react": "^7.26.3",
|
||||
"@docusaurus/module-type-aliases": "3.5.2",
|
||||
"@docusaurus/types": "3.5.2"
|
||||
"@docusaurus/module-type-aliases": "3.7.0",
|
||||
"@docusaurus/types": "3.7.0"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
|
5
sites/org/docs/docs/about/editor/readme.mdx
Normal file
5
sites/org/docs/docs/about/editor/readme.mdx
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: FreeSewing Pattern Editor
|
||||
---
|
||||
|
||||
FIXME: Document v4 editor here
|
|
@ -24,10 +24,12 @@
|
|||
"@mdx-js/react": "^3.0.0",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"clsx": "^2.0.0",
|
||||
"daisyui": "^4.12.23",
|
||||
"lodash": "^4.17.21",
|
||||
"postcss": "^8.4.47",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^18.0.0",
|
||||
"react-dom": "^18.0.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"tailwindcss": "^3.4.14"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import orderBy from 'lodash.orderby'
|
||||
import orderBy from 'lodash/orderBy.js'
|
||||
import set from 'lodash.set'
|
||||
import { mergeOptions } from '@freesewing/core'
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
# The FreeSewing stand-alone development environment
|
||||
|
||||
This is the environment that we ship in the @freesewing/new-design package.
|
||||
|
||||
You can use it inside the monorepo, but that's not its intended purpose.
|
|
@ -1,3 +0,0 @@
|
|||
// __SDEFILE__ - This file is a dependency for the stand-alone environment
|
||||
// SDE does not support this
|
||||
export const examples = false
|
|
@ -1,13 +0,0 @@
|
|||
import { Popout } from 'shared/components/popout/index.mjs'
|
||||
import { WebLink } from 'shared/components/link.mjs'
|
||||
|
||||
// This is how we skip the docs in the sde
|
||||
export const DynamicOrgDocs = () => (
|
||||
<Popout note>
|
||||
<h5>The FreeSewing stand-alone development environment does not include documentation</h5>
|
||||
<p>
|
||||
Go to <WebLink href="https://freesewing.org/" txt="FreeSewing.org" /> if you want all features
|
||||
enabled.
|
||||
</p>
|
||||
</Popout>
|
||||
)
|
|
@ -1,6 +0,0 @@
|
|||
/*
|
||||
* Placeholder feeds component that does nothing
|
||||
* but allows us to re-use code that expects this
|
||||
* to be here
|
||||
*/
|
||||
export const Feeds = () => null
|
|
@ -1,36 +0,0 @@
|
|||
// Dependencies
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { collection } from 'site/hooks/use-design.mjs'
|
||||
// Components
|
||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
||||
import { Link } from 'shared/components/link.mjs'
|
||||
|
||||
export const ns = ['sde']
|
||||
|
||||
export const ModalDesignPicker = () => {
|
||||
const { t } = useTranslation(ns)
|
||||
|
||||
return (
|
||||
<ModalWrapper flex="col" justify="top lg:justify-center" slideFrom="left">
|
||||
<div className="max-w-xl">
|
||||
<h2>{t('sde:chooseATemplate')}</h2>
|
||||
<div className="flex flex-row p-4 w-full flex-wrap gap-2">
|
||||
{collection.map((d) => (
|
||||
<Link
|
||||
href={`/design/${d}`}
|
||||
key={d}
|
||||
className={`btn w-64 btn-secondary flex flex-col flex-nowrap items-start
|
||||
gap-2 py-2 h-auto border border-secondary justify-start text-left bg-opacity-30
|
||||
hover:bg-opacity-20 hover:bg-secondary btn-ghost
|
||||
border border-secondary hover:border hover:border-secondary
|
||||
`}
|
||||
>
|
||||
<div className="text-lg font-bold">{t(`sde:${d}.t`)}</div>
|
||||
<div className={`normal-case text-base-content`}>{t(`sde:${d}.d`)}</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
)
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
import { nsMerge } from 'shared/utils.mjs'
|
||||
// Hooks
|
||||
import { useContext } from 'react'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { useTheme } from 'shared/hooks/use-theme.mjs'
|
||||
// Context
|
||||
import { ModalContext } from 'shared/context/modal-context.mjs'
|
||||
// Components
|
||||
import {
|
||||
DocsIcon,
|
||||
LockIcon,
|
||||
ThemeIcon,
|
||||
I18nIcon,
|
||||
GitHubIcon,
|
||||
HelpIcon,
|
||||
HomeIcon,
|
||||
RocketIcon,
|
||||
} from 'shared/components/icons.mjs'
|
||||
import { HeaderWrapper } from 'shared/components/wrappers/header.mjs'
|
||||
import { ModalThemePicker, ns as themeNs } from 'shared/components/modal/theme-picker.mjs'
|
||||
import { ModalLocalePicker, ns as localeNs } from 'shared/components/modal/locale-picker.mjs'
|
||||
import { ModalDesignPicker } from './design-picker.mjs'
|
||||
|
||||
import { NavButton, NavSpacer } from 'shared/components/header.mjs'
|
||||
|
||||
export const ns = nsMerge('sde', 'header', 'sections', 'susi', themeNs, localeNs)
|
||||
|
||||
const NavIcons = ({ setModal }) => {
|
||||
const { t } = useTranslation(['header'])
|
||||
const { spectrum } = useTheme()
|
||||
const iconSize = 'h-6 w-6 lg:h-12 lg:w-12'
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavButton href="/" label={t('header:home')} color={spectrum[1]}>
|
||||
<HomeIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavSpacer />
|
||||
<NavButton
|
||||
onClick={() => setModal(<ModalDesignPicker />)}
|
||||
label={t('sde:design')}
|
||||
color={spectrum[2]}
|
||||
>
|
||||
<RocketIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavButton href="https://freesewing.dev/" label={t('sde:docs')} color={spectrum[3]}>
|
||||
<DocsIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavButton
|
||||
href="http://github.com/freesewing/freesewing"
|
||||
label={t('sde:code')}
|
||||
color={spectrum[4]}
|
||||
>
|
||||
<GitHubIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavButton href="https://freesewing.org/support" label={t('sde:support')} color={spectrum[5]}>
|
||||
<HelpIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavSpacer />
|
||||
<NavButton
|
||||
onClick={() => setModal(<ModalThemePicker />)}
|
||||
label={t('header:theme')}
|
||||
color={spectrum[6]}
|
||||
>
|
||||
<ThemeIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavButton
|
||||
onClick={() => setModal(<ModalLocalePicker />)}
|
||||
label={t('header:language')}
|
||||
color={spectrum[7]}
|
||||
>
|
||||
<I18nIcon className={iconSize} />
|
||||
</NavButton>
|
||||
<NavSpacer />
|
||||
<NavButton href="/signin" label={t('susi:signIn')} color={spectrum[8]}>
|
||||
<LockIcon className={iconSize} />
|
||||
</NavButton>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const Header = ({ setSearch, show }) => {
|
||||
const { setModal } = useContext(ModalContext)
|
||||
|
||||
return (
|
||||
<HeaderWrapper {...{ setSearch, show }}>
|
||||
<div className="m-auto md:px-8">
|
||||
<div className="p-0 flex flex-row gap-2 justify-between text-neutral-content items-center">
|
||||
{/* Non-mobile content */}
|
||||
<div className="hidden lg:flex lg:flex-row lg:justify-between items-center xl:justify-center w-full">
|
||||
<NavIcons setModal={setModal} setSearch={setSearch} />
|
||||
</div>
|
||||
|
||||
{/* Mobile content */}
|
||||
<div className="flex lg:hidden flex-row items-center justify-between w-full">
|
||||
<NavIcons setModal={setModal} setSearch={setSearch} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</HeaderWrapper>
|
||||
)
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
export const ns = ['']
|
||||
|
||||
export const BareLayout = ({ children }) => children
|
|
@ -1,5 +0,0 @@
|
|||
export const ns = ['']
|
||||
|
||||
export const DefaultLayout = ({ children }) => (
|
||||
<div className="max-w-2xl m-auto px-2 py-8">{children}</div>
|
||||
)
|
|
@ -1,7 +0,0 @@
|
|||
export const ns = []
|
||||
|
||||
export const WorkbenchLayout = (props) => (
|
||||
<section id="fs-workbench" className="m-0 p-0">
|
||||
{props.children}
|
||||
</section>
|
||||
)
|
|
@ -1,28 +0,0 @@
|
|||
// Components
|
||||
import { SectionsMenu, ns as sectionsNs } from 'shared/components/navigation/sections-menu.mjs'
|
||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
||||
import { ChoiceLink } from 'shared/components/choice-link.mjs'
|
||||
|
||||
export const ns = sectionsNs
|
||||
|
||||
export const ModalMenu = () => (
|
||||
<ModalWrapper flex="col" justify="top" slideFrom="left">
|
||||
<div className="max-w-full">
|
||||
<div
|
||||
className={`
|
||||
py-4 w-full m-auto
|
||||
flex flex-col-reverse gap-0 flex-wrap justify-between
|
||||
lg:max-w-6xl lg:flex-nowrap lg:gap-8 lg:flex-row
|
||||
`}
|
||||
>
|
||||
<div className="w-full">
|
||||
<SectionsMenu />
|
||||
<ChoiceLink href="/sitemap" title="Sitemap">
|
||||
The sitemap lists all pages on this website. It can give you a good idea of what you can
|
||||
find here.
|
||||
</ChoiceLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalWrapper>
|
||||
)
|
|
@ -1,2 +0,0 @@
|
|||
export const ns = []
|
||||
export const Search = () => null
|
|
@ -1,45 +0,0 @@
|
|||
// Hooks
|
||||
import { useEffect } from 'react'
|
||||
import { useSwipeable } from 'react-swipeable'
|
||||
import { useRouter } from 'next/router'
|
||||
// Components
|
||||
import { LayoutWrapper } from 'site/components/wrappers/layout.mjs'
|
||||
|
||||
/* This component should wrap all page content */
|
||||
export const PageWrapper = ({
|
||||
title = 'FIXME: No title set',
|
||||
app = false,
|
||||
layout = false,
|
||||
children = [],
|
||||
}) => {
|
||||
const swipeHandlers = useSwipeable({
|
||||
onSwipedLeft: () => (app.primaryMenu ? app.setPrimaryMenu(false) : null),
|
||||
onSwipedRight: () => (app.primaryMenu ? null : app.setPrimaryMenu(true)),
|
||||
trackMouse: true,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
const slug = router.asPath.slice(1)
|
||||
|
||||
useEffect(() => app.setSlug(slug), [slug])
|
||||
|
||||
const childProps = {
|
||||
app: app,
|
||||
title: title,
|
||||
}
|
||||
|
||||
const Layout = layout
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={swipeHandlers.ref}
|
||||
onMouseDown={swipeHandlers.onMouseDown}
|
||||
data-theme={app.theme}
|
||||
key={app.theme} // Thiis forces the data-theme update
|
||||
>
|
||||
<LayoutWrapper {...childProps}>
|
||||
{Layout ? <Layout {...childProps}>{children}</Layout> : children}
|
||||
</LayoutWrapper>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import en from './en.json' assert { type: 'json' }
|
||||
import de from './de.json' assert { type: 'json' }
|
||||
import es from './es.json' assert { type: 'json' }
|
||||
import fr from './fr.json' assert { type: 'json' }
|
||||
import nl from './nl.json' assert { type: 'json' }
|
||||
import uk from './uk.json' assert { type: 'json' }
|
||||
|
||||
export const i18n = { en, de, es, fr, nl, uk }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bella",
|
||||
"d": "This design extends Bella",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { back as bellaBack } from '@freesewing/bella'
|
||||
|
||||
function draftBack({ part }) {
|
||||
// Do your magic here
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const back = {
|
||||
name: 'frombella.back',
|
||||
from: bellaBack,
|
||||
draft: draftBack,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { frontSideDart as bellaFront } from '@freesewing/bella'
|
||||
|
||||
function draftFront({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const front = {
|
||||
name: 'frombella.front',
|
||||
from: bellaFront,
|
||||
draft: draftFront,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
import { Design, mergeI18n } from '@freesewing/core'
|
||||
import { i18n as ourI18n } from '../i18n/index.mjs'
|
||||
import { i18n as bellaI18n } from '@freesewing/bella'
|
||||
import { back } from './back.mjs'
|
||||
import { front } from './front.mjs'
|
||||
|
||||
/*
|
||||
* Create the design
|
||||
*/
|
||||
const FromBella = new Design({
|
||||
data: {
|
||||
name: 'fromBella',
|
||||
version: '0.0.1',
|
||||
},
|
||||
parts: [back, front],
|
||||
})
|
||||
|
||||
/*
|
||||
* Merge translations
|
||||
*/
|
||||
const i18n = mergeI18n([bellaI18n, ourI18n])
|
||||
|
||||
export { back, front, FromBella, i18n }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import en from './en.json' assert { type: 'json' }
|
||||
import de from './de.json' assert { type: 'json' }
|
||||
import es from './es.json' assert { type: 'json' }
|
||||
import fr from './fr.json' assert { type: 'json' }
|
||||
import nl from './nl.json' assert { type: 'json' }
|
||||
import uk from './uk.json' assert { type: 'json' }
|
||||
|
||||
export const i18n = { en, de, es, fr, nl, uk }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Bent",
|
||||
"d": "This design extends Bent",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { back as bentBack } from '@freesewing/bent'
|
||||
|
||||
function draftBack({ part }) {
|
||||
// Do your magic here
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const back = {
|
||||
name: 'frombent.back',
|
||||
from: bentBack,
|
||||
draft: draftBack,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { front as bentFront } from '@freesewing/bent'
|
||||
|
||||
function draftFront({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const front = {
|
||||
name: 'frombent.front',
|
||||
from: bentFront,
|
||||
draft: draftFront,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { Design, mergeI18n } from '@freesewing/core'
|
||||
import { i18n as ourI18n } from '../i18n/index.mjs'
|
||||
import { i18n as bentI18n } from '@freesewing/bent'
|
||||
import { back } from './back.mjs'
|
||||
import { front } from './front.mjs'
|
||||
import { topSleeve } from './top-sleeve.mjs'
|
||||
import { underSleeve } from './under-sleeve.mjs'
|
||||
|
||||
/*
|
||||
* Create the design
|
||||
*/
|
||||
const FromBent = new Design({
|
||||
data: {
|
||||
name: 'fromBent',
|
||||
version: '0.0.1',
|
||||
},
|
||||
parts: [back, front, topSleeve, underSleeve],
|
||||
})
|
||||
|
||||
/*
|
||||
* Merge translations
|
||||
*/
|
||||
const i18n = mergeI18n([bentI18n, ourI18n])
|
||||
|
||||
export { back, front, topSleeve, underSleeve, FromBent, i18n }
|
|
@ -1,16 +0,0 @@
|
|||
import { topSleeve as bentTopSleeve } from '@freesewing/bent'
|
||||
|
||||
function draftTopSleeve({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const topSleeve = {
|
||||
name: 'frombent.topSleeve',
|
||||
from: bentTopSleeve,
|
||||
draft: draftTopSleeve,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { underSleeve as bentUnderSleeve } from '@freesewing/bent'
|
||||
|
||||
function draftUnderSleeve({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const underSleeve = {
|
||||
name: 'frombent.underSleeve',
|
||||
from: bentUnderSleeve,
|
||||
draft: draftUnderSleeve,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import en from './en.json' assert { type: 'json' }
|
||||
import de from './de.json' assert { type: 'json' }
|
||||
import es from './es.json' assert { type: 'json' }
|
||||
import fr from './fr.json' assert { type: 'json' }
|
||||
import nl from './nl.json' assert { type: 'json' }
|
||||
import uk from './uk.json' assert { type: 'json' }
|
||||
|
||||
export const i18n = { en, de, es, fr, nl, uk }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Breanna",
|
||||
"d": "This design extends Breanna",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { back as breannaBack } from '@freesewing/breanna'
|
||||
|
||||
function draftBack({ part }) {
|
||||
// Do your magic here
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const back = {
|
||||
name: 'frombreanna.back',
|
||||
from: breannaBack,
|
||||
draft: draftBack,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { front as breannaFront } from '@freesewing/breanna'
|
||||
|
||||
function draftFront({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const front = {
|
||||
name: 'frombreanna.front',
|
||||
from: breannaFront,
|
||||
draft: draftFront,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { Design, mergeI18n } from '@freesewing/core'
|
||||
import { i18n as ourI18n } from '../i18n/index.mjs'
|
||||
import { i18n as breannaI18n } from '@freesewing/breanna'
|
||||
import { back } from './back.mjs'
|
||||
import { front } from './front.mjs'
|
||||
import { sleeve } from './sleeve.mjs'
|
||||
|
||||
/*
|
||||
* Create the design
|
||||
*/
|
||||
const FromBreanna = new Design({
|
||||
data: {
|
||||
name: 'fromBreanna',
|
||||
version: '0.0.1',
|
||||
},
|
||||
parts: [back, front, sleeve],
|
||||
})
|
||||
|
||||
/*
|
||||
* Merge translations
|
||||
*/
|
||||
const i18n = mergeI18n([breannaI18n, ourI18n])
|
||||
|
||||
export { back, front, sleeve, FromBreanna, i18n }
|
|
@ -1,16 +0,0 @@
|
|||
import { sleeve as breannaSleeve } from '@freesewing/breanna'
|
||||
|
||||
function draftSleeve({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const sleeve = {
|
||||
name: 'frombreanna.sleeve',
|
||||
from: breannaSleeve,
|
||||
draft: draftSleeve,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import en from './en.json' assert { type: 'json' }
|
||||
import de from './de.json' assert { type: 'json' }
|
||||
import es from './es.json' assert { type: 'json' }
|
||||
import fr from './fr.json' assert { type: 'json' }
|
||||
import nl from './nl.json' assert { type: 'json' }
|
||||
import uk from './uk.json' assert { type: 'json' }
|
||||
|
||||
export const i18n = { en, de, es, fr, nl, uk }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "From Brian",
|
||||
"d": "This design extends Brian",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import { back as brianBack } from '@freesewing/brian'
|
||||
|
||||
function draftBack({ part }) {
|
||||
// Do your magic here
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const back = {
|
||||
name: 'frombrian.back',
|
||||
from: brianBack,
|
||||
draft: draftBack,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { front as brianFront } from '@freesewing/brian'
|
||||
|
||||
function draftFront({ part }) {
|
||||
/*
|
||||
* Do your magic here
|
||||
*/
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const front = {
|
||||
name: 'frombrian.front',
|
||||
from: brianFront,
|
||||
draft: draftFront,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
import { Design, mergeI18n } from '@freesewing/core'
|
||||
import { i18n as ourI18n } from '../i18n/index.mjs'
|
||||
import { i18n as brianI18n } from '@freesewing/brian'
|
||||
import { back } from './back.mjs'
|
||||
import { front } from './front.mjs'
|
||||
import { sleeve } from './sleeve.mjs'
|
||||
|
||||
/*
|
||||
* Create the design
|
||||
*/
|
||||
const FromBrian = new Design({
|
||||
data: {
|
||||
name: 'fromBrian',
|
||||
version: '0.0.1',
|
||||
},
|
||||
parts: [back, front, sleeve],
|
||||
})
|
||||
|
||||
/*
|
||||
* Merge translations
|
||||
*/
|
||||
const i18n = mergeI18n([brianI18n, ourI18n])
|
||||
|
||||
export { back, front, sleeve, FromBrian, i18n }
|
|
@ -1,14 +0,0 @@
|
|||
import { sleeve as brianSleeve } from '@freesewing/brian'
|
||||
|
||||
function draftSleeve({ part }) {
|
||||
// Do your magic here
|
||||
|
||||
return part
|
||||
}
|
||||
|
||||
export const sleeve = {
|
||||
name: 'frombrian.sleeve',
|
||||
from: brianSleeve,
|
||||
draft: draftSleeve,
|
||||
hide: { from: true },
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {
|
||||
"whatWillYouCreateToday": "What will you create today?"
|
||||
},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import en from './en.json' assert { type: 'json' }
|
||||
import de from './de.json' assert { type: 'json' }
|
||||
import es from './es.json' assert { type: 'json' }
|
||||
import fr from './fr.json' assert { type: 'json' }
|
||||
import nl from './nl.json' assert { type: 'json' }
|
||||
import uk from './uk.json' assert { type: 'json' }
|
||||
|
||||
export const i18n = { en, de, es, fr, nl, uk }
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"t": "Your Design",
|
||||
"d": "This is your own design, from scratch",
|
||||
"p": {},
|
||||
"s": {},
|
||||
"o": {}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue