diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..1cf23ce --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,87 @@ +name: Check and Publish NPM Version + +on: + push: + branches: + - develop + +jobs: + check-and-publish: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up bun + uses: oven-sh/setup-bun@v2 + + - name: Install and Build + run: | + bun install + bun run build + + - name: Get the latest release + id: get_latest_release + run: | + latest_release=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name) + echo "::set-output name=latest_release::${latest_release}" + + - name: Get version from package.json + id: get_package_version + run: | + package_version=$(jq -r .version < ./package.json) + echo "::set-output name=package_version::${package_version}" + + - name: Compare GitHub release version + id: compare_github_versions + run: | + if [ "${{ steps.get_latest_release.outputs.latest_release }}" == "${{ steps.get_package_version.outputs.package_version }}" ]; then + echo "GitHub release version matches package.json version." + echo "::set-output name=should_create_release::false" + else + echo "GitHub release version does not match package.json version." + echo "::set-output name=should_create_release::true" + fi + + - name: Create GitHub release + if: steps.compare_github_versions.outputs.should_create_release == 'true' + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.get_package_version.outputs.package_version }} + release_name: Release ${{ steps.get_package_version.outputs.package_version }} + draft: false + prerelease: false + + - name: Get latest NPM version + id: get_latest_npm_version + run: | + npm_version=$(npm show $(jq -r .name < ./package.json) version) + echo "::set-output name=npm_version::${npm_version}" + + - name: Compare NPM version + id: compare_npm_versions + run: | + if [ "${{ steps.get_latest_npm_version.outputs.npm_version }}" == "${{ steps.get_package_version.outputs.package_version }}" ]; then + echo "NPM version matches package.json version." + echo "::set-output name=should_publish_npm::false" + else + echo "NPM version does not match package.json version." + echo "::set-output name=should_publish_npm::true" + fi + + - name: Publish to NPM + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + if: steps.compare_npm_versions.outputs.should_publish_npm == 'true' + run: bun run npm publish --//registry.npmjs.org/:_authToken=${NPM_TOKEN} + + - name: Success message + if: steps.compare_github_versions.outputs.should_create_release == 'false' && steps.compare_npm_versions.outputs.should_publish_npm == 'false' || success() + run: echo "NPM package and GitHub release are up to date or published successfully." + + - name: Fail if publish failed + if: failure() + run: exit 1 diff --git a/.gitignore b/.gitignore index a469cc6..da6ab01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ **/coverage +**/dist **/node_modules **/npm-debug.log **/package-lock.json diff --git a/.npmignore b/.npmignore index 314153a..cdb9fd3 100644 --- a/.npmignore +++ b/.npmignore @@ -1,15 +1,7 @@ -**/.circleci **/.eslintrc **/.gitignore **/.vscode -**/jest -**/jest.config.js **/node_modules -**/test-coverage -**/webpack.*.js -**/yarn-error.log -**/demo.* -**/*.html -**/*.test.js -**/*.test.tsx +**/demo +**/*.test.* diff --git a/bun.lockb b/bun.lockb index c5c99ef..ff0a58a 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2fcb891..6fbb3d0 100644 --- a/package.json +++ b/package.json @@ -16,44 +16,30 @@ "repository": "TroyAlford/react-jsx-parser", "version": "1.29.0", "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.12.1", "acorn-jsx": "^5.3.2", "browserslist": "^4.23.1", "core-js": "^3.37.1" }, "devDependencies": { - "@babel/core": "^7.24.7", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-transform-typescript": "^7.24.7", - "@babel/preset-env": "^7.24.7", - "@babel/preset-react": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", - "@babel/runtime-corejs3": "^7.24.7", "@happy-dom/global-registrator": "^14.12.3", "@types/acorn": "^4.0.6", "@types/bun": "^1.1.6", - "@typescript-eslint/eslint-plugin": "^7.14.1", - "@typescript-eslint/parser": "^7.14.1", - "babel-core": "^7.0.0-bridge.0", - "babel-loader": "^9.1.3", + "@typescript-eslint/eslint-plugin": "^7.15.0", + "@typescript-eslint/parser": "^7.15.0", "basis": "TroyAlford/basis", "concurrently": "^8.2.2", "cross-env": "^7.0.3", - "eslint": "^7", + "eslint": "^8.57.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.29.1", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^4.6.2", "mkdirp": "^3.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "source-map-explorer": "^2.5.3", - "terser-webpack-plugin": "^5.3.10", - "typescript": "^5.5.2", - "webpack": "^5.92.1", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" + "typescript": "^5.5.3" }, "optionalDependencies": { "@types/react": "^18.3.3", @@ -63,25 +49,17 @@ "react": ">=18", "react-dom": ">=18" }, - "resolutions": { - "@types/react": "^18", - "@types/react-dom": "^18", - "browserslist": "^4.14.5", - "extend": "^3.0.2", - "merge": "^1.2.1" - }, "scripts": { "build": "bun build:types && bun build:code", "build:code": "bun build --target=browser --outfile=./dist/react-jsx-parser.min.js ./source/index.ts", "build:types": "bun run tsc -p ./tsconfig.json -d --emitDeclarationOnly", "develop": "NODE_ENV=production concurrently -n build,ts,demo -c green,cyan,yellow \"bun build:code --watch\" \"bun build:types --watch\" \"bun serve\"", - "lint": "yarn eslint --ext .js,.ts,.tsx source/", + "lint": "bun eslint --ext .js,.ts,.tsx source/", "postinstall": "npx patch-package", "prebuild": "mkdirp ./dist && rm -rf ./dist/*", "serve": "bun serve --port=8080 --open", - "sourcemap": "yarn build && source-map-explorer ./dist/es5/react-jsx-parser.min.js", - "test": "lint && test", - "types": "" + "sourcemap": "bun build && source-map-explorer ./dist/es5/react-jsx-parser.min.js", + "test": "bun lint && bun test" }, "contributors": [ { diff --git a/source/components/JsxParser.tsx b/source/components/JsxParser.tsx index d8fe9f2..1efe906 100644 --- a/source/components/JsxParser.tsx +++ b/source/components/JsxParser.tsx @@ -1,4 +1,3 @@ -/* global JSX */ import * as Acorn from 'acorn' import * as AcornJSX from 'acorn-jsx' import React, { Fragment, ComponentType, ExoticComponent } from 'react' @@ -24,9 +23,9 @@ export type TProps = { jsx?: string, onError?: (error: Error) => void, showWarnings?: boolean, - renderError?: (props: { error: string }) => JSX.Element | null, + renderError?: (props: { error: string }) => React.ReactNode | null, renderInWrapper?: boolean, - renderUnrecognized?: (tagName: string) => JSX.Element | null, + renderUnrecognized?: (tagName: string) => React.ReactNode | null, } type Scope = Record @@ -54,7 +53,7 @@ export default class JsxParser extends React.Component { private ParsedChildren: ParsedTree = null - #parseJSX = (jsx: string): JSX.Element | JSX.Element[] | null => { + #parseJSX = (jsx: string): React.ReactNode | React.ReactNode[] | null => { const parser = Acorn.Parser.extend(AcornJSX.default({ autoCloseVoidElements: this.props.autoCloseVoidElements, })) @@ -225,7 +224,7 @@ export default class JsxParser extends React.Component { #parseElement = ( element: AcornJSX.JSXElement | AcornJSX.JSXFragment, scope?: Scope, - ): JSX.Element | JSX.Element[] | null => { + ): React.ReactNode | React.ReactNode[] | null => { const { allowUnknownElements, components, componentsOnly, onError } = this.props const { children: childNodes = [] } = element const openingTag = element.type === 'JSXElement' @@ -242,7 +241,7 @@ export default class JsxParser extends React.Component { .map(tag => tag.trim().toLowerCase()).filter(Boolean) if (/^(html|head|body)$/i.test(name)) { - return childNodes.map(c => this.#parseElement(c, scope)) as JSX.Element[] + return childNodes.map(c => this.#parseElement(c, scope)) as React.ReactNode[] } const tagName = name.trim().toLowerCase() if (blacklistedTags.indexOf(tagName) !== -1) { @@ -332,7 +331,7 @@ export default class JsxParser extends React.Component { return React.createElement(component || lowerName, props, children) } - render = (): React.ReactNode => { + render() { const jsx = (this.props.jsx || '').trim().replace(/]*)>/g, '') this.ParsedChildren = this.#parseJSX(jsx) const className = [...new Set(['jsx-parser', ...String(this.props.className).split(' ')])] @@ -342,7 +341,7 @@ export default class JsxParser extends React.Component { return ( this.props.renderInWrapper ?
{this.ParsedChildren}
- : <>{this.ParsedChildren} + : this.ParsedChildren ) } } diff --git a/source/helpers/parseStyle.ts b/source/helpers/parseStyle.ts index a208513..4429dfe 100644 --- a/source/helpers/parseStyle.ts +++ b/source/helpers/parseStyle.ts @@ -9,9 +9,8 @@ type Style = string | Partial */ export const parseStyle = (style: Style): Partial | undefined => { switch (typeof style) { - case 'string': - return style.split(';').filter(r => r) - .reduce((map, rule) => { + case 'string': + return style.split(';').filter(r => r).reduce((map, rule) => { const name = rule.slice(0, rule.indexOf(':')).trim() const value = rule.slice(rule.indexOf(':') + 1).trim() @@ -20,10 +19,10 @@ export const parseStyle = (style: Style): Partial | undefin [camelCase(name)]: value, } }, {}) - case 'object': - return style + case 'object': + return style - default: - return undefined + default: + return undefined } }