git: c92f264109f6 - main - chinese/opencc-cli: New port: Open Chinese Convert CLI - Node.js binding with command line interface

From: Yuri Victorovich <yuri_at_FreeBSD.org>
Date: Fri, 19 Jun 2026 07:31:17 UTC
The branch main has been updated by yuri:

URL: https://cgit.FreeBSD.org/ports/commit/?id=c92f264109f627fd5c248fcb503c4fe03e63180a

commit c92f264109f627fd5c248fcb503c4fe03e63180a
Author:     Yuri Victorovich <yuri@FreeBSD.org>
AuthorDate: 2026-06-19 07:11:46 +0000
Commit:     Yuri Victorovich <yuri@FreeBSD.org>
CommitDate: 2026-06-19 07:31:14 +0000

    chinese/opencc-cli: New port: Open Chinese Convert CLI - Node.js binding with command line interface
---
 chinese/Makefile                                   |   1 +
 chinese/opencc-cli/Makefile                        |  89 +++++++
 chinese/opencc-cli/distinfo                        |   3 +
 chinese/opencc-cli/files/package-lock.json         | 288 +++++++++++++++++++++
 .../patch-node__modules_opencc_node_global.gypi    |  15 ++
 chinese/opencc-cli/pkg-descr                       |   6 +
 chinese/opencc-cli/pkg-plist                       |  53 ++++
 7 files changed, 455 insertions(+)

diff --git a/chinese/Makefile b/chinese/Makefile
index 541216c9d060..534a15ae021a 100644
--- a/chinese/Makefile
+++ b/chinese/Makefile
@@ -67,6 +67,7 @@
     SUBDIR += lunar
     SUBDIR += moettf
     SUBDIR += opencc
+    SUBDIR += opencc-cli
     SUBDIR += opendesktop-fonts
     SUBDIR += oto
     SUBDIR += p5-Date-Chinese
diff --git a/chinese/opencc-cli/Makefile b/chinese/opencc-cli/Makefile
new file mode 100644
index 000000000000..7cb8c68917f9
--- /dev/null
+++ b/chinese/opencc-cli/Makefile
@@ -0,0 +1,89 @@
+PORTNAME=	opencc-cli
+DISTVERSION=	1.3.1
+CATEGORIES=	chinese
+DIST_SUBDIR=	${PORTNAME}
+
+MAINTAINER=	yuri@FreeBSD.org
+COMMENT=	Open Chinese Convert CLI - Node.js binding with command line interface
+WWW=		https://github.com/BYVoid/OpenCC
+
+LICENSE=	APACHE20
+LICENSE_FILE=	${WRKSRC}/node_modules/${PACKAGE_NAME}/LICENSE
+
+FETCH_DEPENDS=	npm:www/npm \
+		jq:textproc/jq \
+		${LOCALBASE}/share/certs/ca-root-nss.crt:security/ca_root_nss
+BUILD_DEPENDS=	npm:www/npm
+
+USES=		compiler:c++20-lang gmake nodejs:run python:build
+
+WRKSRC=		${WRKDIR}/opencc-${DISTVERSION}
+
+PACKAGE_NAME=	opencc
+
+DD=		${DISTDIR}/${DIST_SUBDIR}
+
+FETCH_SCRIPT=	${PORTSDIR}/Tools/scripts/npmjs-fetch-with-dependencies.sh
+
+do-fetch:
+	@${MKDIR} ${DD}
+	@if ! [ -f ${DD}/${DISTNAME}${EXTRACT_SUFX} ]; then \
+		${ECHO} "====> Fetching ${DISTNAME}${EXTRACT_SUFX}" && \
+		${SETENV} TMPDIR=${WRKDIR} LOCALBASE=${LOCALBASE} ${FETCH_SCRIPT} \
+			${PACKAGE_NAME} ${DISTVERSION} \
+			${FILESDIR}/package-lock.json \
+			${DD}/${DISTNAME}${EXTRACT_SUFX}; \
+	fi
+
+do-build:
+	@cd ${WRKSRC}/node_modules/${PACKAGE_NAME} && \
+		${SETENV} HOME=${WRKDIR} PYTHON=${PYTHON_CMD} \
+			node-gyp rebuild --nodedir=${LOCALBASE}
+
+do-install:
+	@${MKDIR} ${STAGEDIR}${PREFIX}/bin ${STAGEDIR}${PREFIX}/lib
+	cd ${WRKSRC} && \
+		${COPYTREE_SHARE} . ${STAGEDIR}${PREFIX}/lib
+	# remove prebuilt binaries for other platforms and their empty directories
+	@${FIND} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/prebuilds -name "*.node" -delete
+	@${FIND} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/prebuilds -type d -mindepth 1 -empty -delete
+	# create directory for FreeBSD prebuilt binary and copy the built one
+	@${MKDIR} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/prebuilds/freebsd-x64
+	@${CP} ${WRKSRC}/node_modules/${PACKAGE_NAME}/build/Release/opencc.node \
+		${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/prebuilds/freebsd-x64/
+	# remove build artifacts, source code, and build tooling
+	@${RM} -r ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/build
+	@${RM} -r ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/src
+	@${RM} -r ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/deps
+	@${RM} -r ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/data
+	@${RM} -r ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/scripts
+	@${RM} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/binding.gyp
+	@${RM} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/*.gypi
+	@${RM} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/*.orig
+	@${RM} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/opencc.cc
+	@${RM} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/opencc_config.h
+	# remove all nested node_modules except node-gyp-build and .bin (the only runtime dependencies)
+	@${FIND} ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node_modules -mindepth 1 -maxdepth 1 \
+		! -name node-gyp-build ! -name .bin -exec ${RM} -r {} +
+	# remove broken symlinks from nested .bin (if it still exists)
+	@if [ -d ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node_modules/.bin ]; then \
+		for f in ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node_modules/.bin/*; do \
+			if [ -L "$$f" ] && ! [ -e "$$f" ]; then ${RM} "$$f"; fi; \
+		done; \
+	fi
+	# remove unnecessary files
+	@${FIND} ${STAGEDIR}${PREFIX}/lib -type f -and -name "README.md" -delete
+	@${FIND} ${STAGEDIR}${PREFIX}/lib -type f -and -name "*.package-lock.json" -delete
+	# fix shebang
+	@${REINPLACE_CMD} -i '' \
+		-e "s|#!/usr/bin/env node|#!${PREFIX}/bin/node|" \
+		${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/cli.js
+	@${CHMOD} +x ${STAGEDIR}${PREFIX}/lib/node_modules/${PACKAGE_NAME}/node/cli.js
+	# create symlink in bin
+	@${LN} -sf ../lib/node_modules/.bin/opencc ${STAGEDIR}${PREFIX}/bin/opencc
+	# remove stray files
+	@${RM} \
+		${STAGEDIR}${LOCALBASE}/lib/package.json \
+		${STAGEDIR}${LOCALBASE}/lib/package-lock.json
+
+.include <bsd.port.mk>
diff --git a/chinese/opencc-cli/distinfo b/chinese/opencc-cli/distinfo
new file mode 100644
index 000000000000..45aedeb9e777
--- /dev/null
+++ b/chinese/opencc-cli/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1781852050
+SHA256 (opencc-cli/opencc-cli-1.3.1.tar.gz) = 7413b9547c43b08e46aec8b0d28479377aaacadfb31547e12cc452d9f19bfd5e
+SIZE (opencc-cli/opencc-cli-1.3.1.tar.gz) = 3701315
diff --git a/chinese/opencc-cli/files/package-lock.json b/chinese/opencc-cli/files/package-lock.json
new file mode 100644
index 000000000000..9276070cfd10
--- /dev/null
+++ b/chinese/opencc-cli/files/package-lock.json
@@ -0,0 +1,288 @@
+{
+  "name": "opencc-installer",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "opencc-installer",
+      "version": "1.0.0",
+      "dependencies": {
+        "opencc": "^1.3.1"
+      }
+    },
+    "node_modules/opencc": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/opencc/-/opencc-1.3.1.tgz",
+      "integrity": "sha512-YIlqNnB0eM94oRhlUsnlYHwYHxvEyd138ZoqPuAcZW+IHXT4vkJuhemcqcU4AZfoPupmRt/OIJGXcrOfZu3Tmw==",
+      "hasInstallScript": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "node-addon-api": "^8.7.0",
+        "node-gyp": "^12.3.0",
+        "node-gyp-build": "^4.8.4"
+      },
+      "bin": {
+        "opencc": "node/cli.js"
+      },
+      "engines": {
+        "node": ">=20.17"
+      }
+    },
+    "node_modules/opencc/node_modules/@isaacs/fs-minipass": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+      "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+      "license": "ISC",
+      "dependencies": {
+        "minipass": "^7.0.4"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/opencc/node_modules/abbrev": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-4.0.0.tgz",
+      "integrity": "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA==",
+      "license": "ISC",
+      "engines": {
+        "node": "^20.17.0 || >=22.9.0"
+      }
+    },
+    "node_modules/opencc/node_modules/chownr": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+      "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/opencc/node_modules/env-paths": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+      "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/opencc/node_modules/exponential-backoff": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz",
+      "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/opencc/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/opencc/node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/opencc/node_modules/isexe": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz",
+      "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=20"
+      }
+    },
+    "node_modules/opencc/node_modules/minipass": {
+      "version": "7.1.3",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+      "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      }
+    },
+    "node_modules/opencc/node_modules/minizlib": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
+      "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
+      "license": "MIT",
+      "dependencies": {
+        "minipass": "^7.1.2"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/opencc/node_modules/node-addon-api": {
+      "version": "8.8.0",
+      "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.8.0.tgz",
+      "integrity": "sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA==",
+      "license": "MIT",
+      "engines": {
+        "node": "^18 || ^20 || >= 21"
+      }
+    },
+    "node_modules/opencc/node_modules/node-gyp": {
+      "version": "12.4.0",
+      "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-12.4.0.tgz",
+      "integrity": "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw==",
+      "license": "MIT",
+      "dependencies": {
+        "env-paths": "^2.2.0",
+        "exponential-backoff": "^3.1.1",
+        "graceful-fs": "^4.2.6",
+        "nopt": "^9.0.0",
+        "proc-log": "^6.0.0",
+        "semver": "^7.3.5",
+        "tar": "^7.5.4",
+        "tinyglobby": "^0.2.12",
+        "undici": "^6.25.0",
+        "which": "^6.0.0"
+      },
+      "bin": {
+        "node-gyp": "bin/node-gyp.js"
+      },
+      "engines": {
+        "node": "^20.17.0 || >=22.9.0"
+      }
+    },
+    "node_modules/opencc/node_modules/node-gyp-build": {
+      "version": "4.8.4",
+      "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+      "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+      "license": "MIT",
+      "bin": {
+        "node-gyp-build": "bin.js",
+        "node-gyp-build-optional": "optional.js",
+        "node-gyp-build-test": "build-test.js"
+      }
+    },
+    "node_modules/opencc/node_modules/nopt": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/nopt/-/nopt-9.0.0.tgz",
+      "integrity": "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw==",
+      "license": "ISC",
+      "dependencies": {
+        "abbrev": "^4.0.0"
+      },
+      "bin": {
+        "nopt": "bin/nopt.js"
+      },
+      "engines": {
+        "node": "^20.17.0 || >=22.9.0"
+      }
+    },
+    "node_modules/opencc/node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/opencc/node_modules/proc-log": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-6.1.0.tgz",
+      "integrity": "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ==",
+      "license": "ISC",
+      "engines": {
+        "node": "^20.17.0 || >=22.9.0"
+      }
+    },
+    "node_modules/opencc/node_modules/semver": {
+      "version": "7.8.4",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
+      "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/opencc/node_modules/tar": {
+      "version": "7.5.16",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.16.tgz",
+      "integrity": "sha512-56adEpPMouktRlBLXiaYFFzZ/3+JXa8P9n7WbR+ibIjtviN55mEaOkiysCnPnWm+7kkui1Dn8J9l+g6zV8731w==",
+      "license": "BlueOak-1.0.0",
+      "dependencies": {
+        "@isaacs/fs-minipass": "^4.0.0",
+        "chownr": "^3.0.0",
+        "minipass": "^7.1.2",
+        "minizlib": "^3.1.0",
+        "yallist": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/opencc/node_modules/tinyglobby": {
+      "version": "0.2.17",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
+      "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
+      "license": "MIT",
+      "dependencies": {
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.4"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/opencc/node_modules/undici": {
+      "version": "6.27.0",
+      "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz",
+      "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18.17"
+      }
+    },
+    "node_modules/opencc/node_modules/which": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/which/-/which-6.0.1.tgz",
+      "integrity": "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==",
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^4.0.0"
+      },
+      "bin": {
+        "node-which": "bin/which.js"
+      },
+      "engines": {
+        "node": "^20.17.0 || >=22.9.0"
+      }
+    },
+    "node_modules/opencc/node_modules/yallist": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+      "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+      "license": "BlueOak-1.0.0",
+      "engines": {
+        "node": ">=18"
+      }
+    }
+  }
+}
diff --git a/chinese/opencc-cli/files/patch-node__modules_opencc_node_global.gypi b/chinese/opencc-cli/files/patch-node__modules_opencc_node_global.gypi
new file mode 100644
index 000000000000..fd5f9f6b2117
--- /dev/null
+++ b/chinese/opencc-cli/files/patch-node__modules_opencc_node_global.gypi
@@ -0,0 +1,15 @@
+-- Add FreeBSD to the OS condition for C++20 and exception flags.
+-- The original file only handles linux, mac, and win. FreeBSD needs
+-- the same compiler flags as linux (-std=c++20, no -fno-exceptions).
+
+--- node_modules/opencc/node/global.gypi.orig	2026-06-19 06:56:40 UTC
++++ node_modules/opencc/node/global.gypi
+@@ -8,7 +8,7 @@
+     ],
+     "conditions": [
+       [
+-        "OS==\"linux\"",
++        "OS==\"linux\" or OS==\"freebsd\"",
+         {
+           "cflags": [
+             "-std=c++20"
diff --git a/chinese/opencc-cli/pkg-descr b/chinese/opencc-cli/pkg-descr
new file mode 100644
index 000000000000..4222efa4d578
--- /dev/null
+++ b/chinese/opencc-cli/pkg-descr
@@ -0,0 +1,6 @@
+Open Chinese Convert (OpenCC) is an open source Simplified-Traditional
+Chinese conversion project, providing high quality thesaurus and libopencc,
+as well as a conversion utility and a dictionary generator.
+
+This port provides the Node.js binding with a command line interface
+for converting between Simplified and Traditional Chinese.
diff --git a/chinese/opencc-cli/pkg-plist b/chinese/opencc-cli/pkg-plist
new file mode 100644
index 000000000000..06ff76d3e401
--- /dev/null
+++ b/chinese/opencc-cli/pkg-plist
@@ -0,0 +1,53 @@
+bin/opencc
+lib/node_modules/.bin/opencc
+lib/node_modules/opencc/LICENSE
+lib/node_modules/opencc/node/cli.js
+lib/node_modules/opencc/node/dict.js
+lib/node_modules/opencc/node/opencc.d.cts
+lib/node_modules/opencc/node/opencc.d.mts
+lib/node_modules/opencc/node/opencc.d.ts
+lib/node_modules/opencc/node/opencc.js
+lib/node_modules/opencc/node/opencc.mjs
+lib/node_modules/opencc/node_modules/.bin/node-gyp-build
+lib/node_modules/opencc/node_modules/.bin/node-gyp-build-optional
+lib/node_modules/opencc/node_modules/.bin/node-gyp-build-test
+lib/node_modules/opencc/node_modules/node-gyp-build/LICENSE
+lib/node_modules/opencc/node_modules/node-gyp-build/SECURITY.md
+lib/node_modules/opencc/node_modules/node-gyp-build/bin.js
+lib/node_modules/opencc/node_modules/node-gyp-build/build-test.js
+lib/node_modules/opencc/node_modules/node-gyp-build/index.js
+lib/node_modules/opencc/node_modules/node-gyp-build/node-gyp-build.js
+lib/node_modules/opencc/node_modules/node-gyp-build/optional.js
+lib/node_modules/opencc/node_modules/node-gyp-build/package.json
+lib/node_modules/opencc/package.json
+lib/node_modules/opencc/prebuilds/assets/HKVariants.ocd2
+lib/node_modules/opencc/prebuilds/assets/HKVariantsRev.ocd2
+lib/node_modules/opencc/prebuilds/assets/HKVariantsRevPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/JPShinjitaiCharacters.ocd2
+lib/node_modules/opencc/prebuilds/assets/JPShinjitaiPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/JPVariants.ocd2
+lib/node_modules/opencc/prebuilds/assets/JPVariantsRev.ocd2
+lib/node_modules/opencc/prebuilds/assets/STCharacters.ocd2
+lib/node_modules/opencc/prebuilds/assets/STPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/TSCharacters.ocd2
+lib/node_modules/opencc/prebuilds/assets/TSPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/TWPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/TWPhrasesRev.ocd2
+lib/node_modules/opencc/prebuilds/assets/TWVariants.ocd2
+lib/node_modules/opencc/prebuilds/assets/TWVariantsRev.ocd2
+lib/node_modules/opencc/prebuilds/assets/TWVariantsRevPhrases.ocd2
+lib/node_modules/opencc/prebuilds/assets/hk2s.json
+lib/node_modules/opencc/prebuilds/assets/hk2t.json
+lib/node_modules/opencc/prebuilds/assets/jp2t.json
+lib/node_modules/opencc/prebuilds/assets/s2hk.json
+lib/node_modules/opencc/prebuilds/assets/s2t.json
+lib/node_modules/opencc/prebuilds/assets/s2tw.json
+lib/node_modules/opencc/prebuilds/assets/s2twp.json
+lib/node_modules/opencc/prebuilds/assets/t2hk.json
+lib/node_modules/opencc/prebuilds/assets/t2jp.json
+lib/node_modules/opencc/prebuilds/assets/t2s.json
+lib/node_modules/opencc/prebuilds/assets/t2tw.json
+lib/node_modules/opencc/prebuilds/assets/tw2s.json
+lib/node_modules/opencc/prebuilds/assets/tw2sp.json
+lib/node_modules/opencc/prebuilds/assets/tw2t.json
+lib/node_modules/opencc/prebuilds/freebsd-x64/opencc.node