Repository: zh-lx/pinyin-pro (ts)

Issue:
first isn't consistent
## bug 描述

first 在 `pattern: 'first'` 和 `type: 'all'` 中表现不一致：
- `pattern: 'first'` 中无论是否中文，都返回结果第一个字符
- `type: 'all'`: 是中文则返回结果第一个字符，非中文返回空字符串

## 你预期的样子是？

是中文则返回结果第一个字符，非中文返回非中文字符串

## pinyin-pro 版本号

`3.25.0`

Pull request description:
feat: keep consistent for first
close #278 

目前 first 在 `pattern: 'first'` 和 `type: 'all'` 中表现不一致：
- `pattern: 'first'` 中无论是否中文，都返回结果第一个字符
- `type: 'all'`: 是中文则返回结果第一个字符，非中文返回空字符串

修改为： 是中文则返回结果第一个字符，非中文返回非中文字符串

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f956ba0..83aa2cb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,5 @@
 # 更新日志
 
-## 3.25.0
-
-- 【feat】`match` API 新增 `v` 选项，允许使用 `v` 匹配 `ü` 的拼音 [#276](https://github.com/zh-lx/pinyin-pro/pull/276)
-
 ## 3.24.2
 
 - 【feat】`html` API 增加 `rp` 选项，用于去除输出结果中的 `<rp>(</rp>` 和 `<rp>)</rp>` [#272](https://github.com/zh-lx/pinyin-pro/pull/272)
diff --git a/lib/core/match/index.ts b/lib/core/match/index.ts
index 1440d7f..352eb57 100644
--- a/lib/core/match/index.ts
+++ b/lib/core/match/index.ts
@@ -22,10 +22,6 @@ interface MatchOptions {
    * @description 是否大小写不敏感
    */
   insensitive?: boolean;
-  /**
-   * @description 是否将 ü 替换成 v 进行匹配
-   */
-  v?: boolean;
 }
 
 const DefaultMatchOptions: MatchOptions = {
@@ -34,7 +30,6 @@ const DefaultMatchOptions: MatchOptions = {
   space: "ignore",
   lastPrecision: "start",
   insensitive: true,
-  v: false,
 };
 
 const MAX_PINYIN_LENGTH = 6;
@@ -50,9 +45,6 @@ export const match = (text: string, pinyin: string, options?: MatchOptions) => {
   if (options?.precision === "any") {
     options.lastPrecision = "any";
   }
-  if (options?.v) {
-    pinyin = pinyin.replace(/ü/g, "v");
-  }
   const completeOptions = {
     ...DefaultMatchOptions,
     ...(options || {}),
@@ -109,7 +101,6 @@ const matchAny = (
       toneType: "none",
       multiple: true,
       type: "array",
-      v: options.v,
     });
     let currentLength = 0;
     ps.forEach((p) => {
@@ -188,7 +179,6 @@ const matchAboveStart = (
           type: "array",
           toneType: "none",
           multiple: true,
-          v: options.v,
         });
 
         // 非中文匹配
diff --git a/lib/core/pinyin/handle.ts b/lib/core/pinyin/handle.ts
index 01a352b..7e2cdde 100644
--- a/lib/core/pinyin/handle.ts
+++ b/lib/core/pinyin/handle.ts
@@ -12,9 +12,7 @@ import { getCustomMultpileDict } from "@/core/custom";
 import { SingleWordResult } from "../../common/type";
 import type { SurnameMode } from "../../common/type";
 import { acTree, MatchPattern, TokenizationAlgorithm } from "../../common/segmentit";
-import {
-  Priority,
-} from "@/common/constant";
+import {  Priority } from "@/common/constant";
 import { splitString } from "@/common/utils";
 
 /**
@@ -275,12 +273,12 @@ const getPinyinWithNum: GetPinyinWithNum = (pinyin, originPinyin) => {
  * @param {string} pinyin
  * @return {string}
  */
-type GetFirstLetter = (pinyin: string) => string;
-const getFirstLetter: GetFirstLetter = (pinyin) => {
+type GetFirstLetter = (pinyin: string, isZh: boolean) => string;
+const getFirstLetter: GetFirstLetter = (pinyin: string, isZh: boolean) => {
   const first_letter_arr: string[] = [];
   const pinyin_arr = pinyin.split(" ");
   pinyin_arr.forEach((pinyin) => {
-    first_letter_arr.push(pinyin[0]);
+    first_letter_arr.push(isZh ? pinyin[0] : pinyin);
   });
   return first_letter_arr.join(" ");
 };
diff --git a/lib/core/pinyin/middlewares.ts b/lib/core/pinyin/middlewares.ts
index 746332f..97bbcd5 100644
--- a/lib/core/pinyin/middlewares.ts
+++ b/lib/core/pinyin/middlewares.ts
@@ -95,8 +95,7 @@ export const middlewarePattern = (
       break;
     case "first":
       list.forEach((item) => {
-        // todo: first 暂时不作为拼音一部分，不进行 isZh 识别
-        item.result = getFirstLetter(item.result);
+        item.result = getFirstLetter(item.result, item.isZh);
       });
       break;
     case "finalHead":
@@ -199,7 +198,7 @@ export const middlewareType = (
         pinyin,
         initial,
         final,
-        first: item.isZh ? getFirstLetter(item.result) : "",
+        first: getFirstLetter(item.result, item.isZh),
         finalHead: head,
         finalBody: body,
         finalTail: tail,
diff --git a/lib/core/polyphonic/index.ts b/lib/core/polyphonic/index.ts
index af56e21..1dcc245 100644
--- a/lib/core/polyphonic/index.ts
+++ b/lib/core/polyphonic/index.ts
@@ -249,7 +249,7 @@ export const handleType = (
         pinyin,
         initial,
         final,
-        first: item.isZh ? getFirstLetter(item.result) : '',
+        first: getFirstLetter(item.result, item.isZh),
         finalHead: head,
         finalBody: body,
         finalTail: tail,
diff --git a/package.json b/package.json
index 8b10d3d..2332d03 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "pinyin-pro",
-  "version": "3.25.0",
+  "version": "3.24.2",
   "description": "准确率和性能最优异的汉字转拼音库。获取中文拼音、韵母、声母、声调、首字母，支持拼音匹配",
   "main": "./dist/index.js",
   "module": "./dist/index.mjs",
@@ -75,6 +75,5 @@
     "commitizen": {
       "path": "node_modules/cz-conventional-changelog"
     }
-  },
-  "sideEffects": false
+  }
 }
diff --git a/types/core/match/index.d.ts b/types/core/match/index.d.ts
index e8f3361..43cc442 100644
--- a/types/core/match/index.d.ts
+++ b/types/core/match/index.d.ts
@@ -19,10 +19,6 @@ interface MatchOptions {
      * @description 是否大小写不敏感
      */
     insensitive?: boolean;
-    /**
-     * @description 是否将 ü 替换成 v 进行匹配
-     */
-    v?: boolean;
 }
 /**
  * @description: 检测汉语字符串和拼音是否匹配


Test patch:
diff --git a/test/all.test.js b/test/all.test.js
index 688c540..eb74bed 100644
--- a/test/all.test.js
+++ b/test/all.test.js
@@ -99,7 +99,7 @@ describe('all', () => {
         pinyin: '',
         initial: '',
         final: '',
-        first: '',
+        first: 'a',
         finalHead: '',
         finalBody: '',
         finalTail: '',
@@ -114,7 +114,7 @@ describe('all', () => {
         pinyin: '',
         initial: '',
         final: '',
-        first: '',
+        first: '𧒽',
         finalHead: '',
         finalBody: '',
         finalTail: '',
@@ -207,7 +207,7 @@ describe('all', () => {
         pinyin: '',
         initial: '',
         final: '',
-        first: '',
+        first: 'a𧒽',
         finalHead: '',
         finalBody: '',
         finalTail: '',
diff --git a/test/match.test.js b/test/match.test.js
index 6fb59dd..cf3f190 100644
--- a/test/match.test.js
+++ b/test/match.test.js
@@ -1,199 +1,174 @@
-import { match, customPinyin, clearCustomDict } from "../lib/index";
-import { expect, describe, it } from "vitest";
+import { match, customPinyin, clearCustomDict } from '../lib/index';
+import { expect, describe, it } from 'vitest';
 
-describe("match", () => {
-  it("[match]default", () => {
-    const result = match("欢迎使用汉语拼音", "hy");
+describe('match', () => {
+  it('[match]default', () => {
+    const result = match('欢迎使用汉语拼音', 'hy');
     expect(result).to.deep.equal([0, 1]);
   });
 
-  it("[match]start and continuous", () => {
-    const result = match("欢迎使用汉语拼音", "yingshyon", {
-      precision: "start",
+  it('[match]start and continuous', () => {
+    const result = match('欢迎使用汉语拼音', 'yingshyon', {
+      precision: 'start',
       continuous: true,
     });
     expect(result).to.deep.equal([1, 2, 3]);
   });
 
-  it("[match]multiple1", () => {
-    const result = match("会计", "kj");
+  it('[match]multiple1', () => {
+    const result = match('会计', 'kj');
     expect(result).to.deep.equal([0, 1]);
   });
 
-  it("[match]multiple2", () => {
-    const result = match("会计", "huij");
+  it('[match]multiple2', () => {
+    const result = match('会计', 'huij');
     expect(result).to.deep.equal([0, 1]);
   });
 
-  it("[match]any", () => {
-    const result = match("开会", "kaiui", { precision: "any" });
+  it('[match]any', () => {
+    const result = match('开会', 'kaiui', { precision: 'any' });
     expect(result).to.deep.equal([0, 1]);
   });
 
-  it("[match]any&empty", () => {
-    const result = match("开会", "", { precision: "any" });
+  it('[match]any&empty', () => {
+    const result = match('开会', '', { precision: 'any' });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]any&continuous", () => {
-    const result = match("开个大会", "kaiui", {
-      precision: "any",
+  it('[match]any&continuous', () => {
+    const result = match('开个大会', 'kaiui', {
+      precision: 'any',
       continuous: true,
     });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]any&nonZh", () => {
-    const result = match("开会", "kaiuiaaaa", { precision: "any" });
+  it('[match]any&nonZh', () => {
+    const result = match('开会', 'kaiuiaaaa', { precision: 'any' });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]any&space", () => {
-    const result = match("开      会s  啊", "kaiuisa", { precision: "any" });
+  it('[match]any&space', () => {
+    const result = match('开      会s  啊', 'kaiuisa', { precision: 'any' });
     expect(result).to.deep.equal([0, 7, 8, 11]);
   });
 
-  it("[match]fail with sucess", () => {
-    const result = match("开会", "kaig");
+  it('[match]fail with sucess', () => {
+    const result = match('开会', 'kaig');
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]fail", () => {
-    const result = match("开会", "l");
+  it('[match]fail', () => {
+    const result = match('开会', 'l');
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]uncontinuous", () => {
-    const result = match("汉语拼音", "hanpin");
+  it('[match]uncontinuous', () => {
+    const result = match('汉语拼音', 'hanpin');
     expect(result).to.deep.equal([0, 2]);
   });
 
-  it("[match]basic", () => {
-    const result = match("汉语拼音", "hyupy");
+  it('[match]basic', () => {
+    const result = match('汉语拼音', 'hyupy');
     expect(result).to.deep.equal([0, 1, 2, 3]);
   });
 
-  it("[match]first & double unicode", () => {
-    const result = match("𧒽测试", "cs");
+  it('[match]first & double unicode', () => {
+    const result = match('𧒽测试', 'cs');
     expect(result).to.deep.equal([2, 3]);
   });
 
-  it("[match]start", () => {
-    const result = match("欢迎使用汉语拼音", "欢yingshy", {
-      precision: "start",
+  it('[match]start', () => {
+    const result = match('欢迎使用汉语拼音', '欢yingshy', {
+      precision: 'start',
     });
     expect(result).to.deep.equal([0, 1, 2, 3]);
   });
 
-  it("[match]first&space", () => {
-    const result = match("𧒽测 试", "c s");
+  it('[match]first&space', () => {
+    const result = match('𧒽测 试', 'c s');
     expect(result).to.deep.equal([2, 4]);
   });
 
-  it("[match]first&space", () => {
-    customPinyin(
-      {
-        𧒽: "lei",
-      },
-      {
-        multiple: "replace",
-      }
-    );
-    const result = match("𧒽测 试", "l c s");
+  it('[match]first&space', () => {
+    customPinyin({
+      𧒽: 'lei'
+    }, {
+      multiple: 'replace'
+    })
+    const result = match('𧒽测 试', 'l c s');
     expect(result).to.deep.equal([0, 1, 2, 4]);
-    clearCustomDict(["pinyin", "multiple", "polyphonic"]);
+    clearCustomDict(['pinyin', 'multiple', 'polyphonic']);
   });
 
-  it("[match]nonZh match", () => {
-    const result = match("测uuuuuuuuuu试", "cuuuuuu");
+  it('[match]nonZh match', () => {
+    const result = match('测uuuuuuuuuu试', 'cuuuuuu');
     expect(result).to.deep.equal([0, 1, 2, 3, 4, 5, 6]);
   });
 
-  it("[match]lastPrecision every fail", () => {
-    const result = match("汉语拼音", "hanyupinyi", { lastPrecision: "every" });
+  it('[match]lastPrecision every fail', () => {
+    const result = match('汉语拼音', 'hanyupinyi', { lastPrecision: 'every' });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]lastPrecision every success", () => {
-    const result = match("汉语拼音", "hanyupinyin", { lastPrecision: "every" });
+  it('[match]lastPrecision every success', () => {
+    const result = match('汉语拼音', 'hanyupinyin', { lastPrecision: 'every' });
     expect(result).to.deep.equal([0, 1, 2, 3]);
   });
 
-  it("[match]lastPrecision first fail", () => {
-    const result = match("汉语拼音", "hanyupinyi", { lastPrecision: "first" });
+  it('[match]lastPrecision first fail', () => {
+    const result = match('汉语拼音', 'hanyupinyi', { lastPrecision: 'first' });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]lastPrecision first success", () => {
-    const result = match("汉语拼音", "hanyupiny", { lastPrecision: "first" });
+  it('[match]lastPrecision first success', () => {
+    const result = match('汉语拼音', 'hanyupiny', { lastPrecision: 'first' });
     expect(result).to.deep.equal([0, 1, 2, 3]);
   });
 
-  it("[match]lastPrecision any", () => {
-    const result = match("汉语拼音", "hanyupini", { lastPrecision: "any" });
+  it('[match]lastPrecision any', () => {
+    const result = match('汉语拼音', 'hanyupini', { lastPrecision: 'any' });
     expect(result).to.deep.equal([0, 1, 2, 3]);
   });
 
-  it("[match]lastPrecision ignore space", () => {
-    const result = match("汉语 拼音", "hanyu pini", {
-      lastPrecision: "any",
-      space: "ignore",
-    });
+  it('[match]lastPrecision ignore space', () => {
+    const result = match('汉语 拼音', 'hanyu pini', { lastPrecision: 'any', space: 'ignore' });
     expect(result).to.deep.equal([0, 1, 3, 4]);
   });
 
-  it("[match]lastPrecision preserve space", () => {
-    const result = match("汉语 拼音", "hanyu pini", {
-      lastPrecision: "any",
-      space: "preserve",
-    });
+  it('[match]lastPrecision preserve space', () => {
+    const result = match('汉语 拼音', 'hanyu pini', { lastPrecision: 'any', space: 'preserve' });
     expect(result).to.deep.equal([0, 1, 2, 3, 4]);
   });
 
-  it("[match]precision preserve space", () => {
-    const result = match("汉语 拼音", "hanyu pini", {
-      precision: "any",
-      space: "preserve",
-    });
+  it('[match]precision preserve space', () => {
+    const result = match('汉语 拼音', 'hanyu pini', { precision: 'any', space: 'preserve' });
     expect(result).to.deep.equal([0, 1, 2, 3, 4]);
   });
 
-  it("[match]precision not continuous", () => {
-    const result = match("汉语 拼音", "hanyu yin", {
-      precision: "any",
-      space: "preserve",
-      continuous: true,
-    });
+  it('[match]precision not continuous', () => {
+    const result = match('汉语 拼音', 'hanyu yin', { precision: 'any', space: 'preserve', continuous: true });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]precision continuous", () => {
-    const result = match("汉语 拼音", "hanyu pinyin", {
-      precision: "any",
-      space: "preserve",
-      continuous: true,
-    });
+  it('[match]precision continuous', () => {
+    const result = match('汉语 拼音', 'hanyu pinyin', { precision: 'any', space: 'preserve', continuous: true });
     expect(result).to.deep.equal([0, 1, 2, 3, 4]);
   });
 
-  it("[match]lastPrecision none", () => {
+  it('[match]lastPrecision none', () => {
     // @ts-ignore
-    const result = match("汉语拼音", "hanyupini", { lastPrecision: "none" });
+    const result = match('汉语拼音', 'hanyupini', { lastPrecision: 'none' });
     expect(result).to.deep.equal(null);
   });
 
-  it("[match]insensitive", () => {
-    const result = match("汉语KK拼音", "hanyukkpinyin");
+  it('[match]insensitive', () => {
+    const result = match('汉语KK拼音', 'hanyukkpinyin');
     expect(result).to.deep.equal([0, 1, 2, 3, 4, 5]);
 
-    const result1 = match("汉语KK拼音", "hanyukkpinyin", {
+    const result1 = match('汉语KK拼音', 'hanyukkpinyin', {
       insensitive: false,
     });
     expect(result1).to.deep.equal(null);
   });
-
-  it("[match]v", () => {
-    const result = match("我是吕布", "woshilvbu", { v: true });
-    expect(result).to.deep.equal([0, 1, 2, 3]);
-  });
 });
diff --git a/test/polyphonic.test.js b/test/polyphonic.test.js
index 114587a..a5fd3e4 100644
--- a/test/polyphonic.test.js
+++ b/test/polyphonic.test.js
@@ -220,7 +220,7 @@ describe('polyphonic', () => {
           finalBody: '',
           finalHead: '',
           finalTail: '',
-          first: '',
+          first: 's',
           initial: '',
           isZh: false,
           num: 0,