Skip to content

Commit a0b9c49

Browse files
committed
fix
解决url里#号被解析成标签
1 parent e8dcd8b commit a0b9c49

10 files changed

Lines changed: 69 additions & 51 deletions

File tree

backend/dist/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
This folder contains the built output assets for the worker "memos-api" generated at 2026-04-08T07:17:37.001Z.
1+
This folder contains the built output assets for the worker "memos-api" generated at 2026-04-21T11:50:17.283Z.

backend/dist/index.js

Lines changed: 20 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/dist/index.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/src/handlers/memos.js

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Hono } from 'hono';
22
import { requireAuth, jsonResponse, errorResponse, hashPassword, generateSecurePassword } from '../utils/auth';
33
import { simpleMD5 } from '../utils/gravatar';
44
import { sendAllNotifications } from '../utils/notifications.js';
5-
import { attachTagToMemo } from '../utils/tags.js';
5+
import { attachTagToMemo, extractTagNamesFromMemoContent } from '../utils/tags.js';
66

77
const app = new Hono();
88

@@ -919,13 +919,7 @@ app.post('/', async (c) => {
919919
}
920920

921921
// 提取并保存标签(但保留在内容中)
922-
const tagNames = [];
923-
924-
if (body.content) {
925-
const tagRegex = /#([^\s#]+)/g;
926-
const tagMatches = [...body.content.matchAll(tagRegex)];
927-
tagNames.push(...new Set(tagMatches.map(match => match[1]))); // 去重
928-
}
922+
const tagNames = extractTagNamesFromMemoContent(body.content);
929923

930924
const stmt = db.prepare(`
931925
INSERT INTO memos (creator_id, content, visibility, display_ts)

backend/src/handlers/telegram.js

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,11 @@ import {
99
sendTelegramNotification,
1010
} from '../utils/notifications.js';
1111
import { callTelegramApi, sendTelegramText } from '../utils/telegram.js';
12-
import { attachTagToMemo } from '../utils/tags.js';
12+
import { attachTagToMemo, extractTagNamesFromMemoContent } from '../utils/tags.js';
1313

1414
const app = new Hono();
1515
const VALID_VISIBILITIES = ['PRIVATE', 'PROTECTED', 'PUBLIC'];
1616

17-
function extractTagNames(content) {
18-
if (!content) {
19-
return [];
20-
}
21-
22-
const tagRegex = /#([^\s#]+)/g;
23-
const tagMatches = [...content.matchAll(tagRegex)];
24-
return [...new Set(tagMatches.map((match) => match[1]))];
25-
}
26-
2717
function buildSettingsMap(settings) {
2818
const settingsMap = {};
2919
(settings || []).forEach((setting) => {
@@ -90,7 +80,7 @@ async function createTelegramMemo(db, user, content) {
9080
`).bind(user.id, content, visibility, now).run();
9181

9282
const memoId = insertResult.meta.last_row_id;
93-
const tagNames = extractTagNames(content);
83+
const tagNames = extractTagNamesFromMemoContent(content);
9484
await ensureMemoTags(db, memoId, tagNames, user.id);
9585

9686
return {

backend/src/utils/tags.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
let cachedTagSchemaPromise = null;
2+
const CODE_BLOCK_REG = /```[\s\S]*?```/g;
3+
const INLINE_CODE_REG = /`[^`\n]*`/g;
4+
const MARKDOWN_LINK_REG = /!?\[[^\]]*\]\([^)]+\)/g;
5+
const PLAIN_LINK_REG = /(?:https?|chrome|edge):\/\/\S+/g;
6+
const TAG_NAME_REG = /#([^\s#,]+)/g;
27

38
function buildTagSelectColumns(schema) {
49
return [
@@ -39,6 +44,24 @@ export async function getTagSchema(db) {
3944
return cachedTagSchemaPromise;
4045
}
4146

47+
function stripIgnoredTagSegments(content = '') {
48+
return content
49+
.replace(CODE_BLOCK_REG, ' ')
50+
.replace(INLINE_CODE_REG, ' ')
51+
.replace(MARKDOWN_LINK_REG, ' ')
52+
.replace(PLAIN_LINK_REG, ' ');
53+
}
54+
55+
export function extractTagNamesFromMemoContent(content) {
56+
if (!content) {
57+
return [];
58+
}
59+
60+
const sanitizedContent = stripIgnoredTagSegments(content);
61+
const tagMatches = [...sanitizedContent.matchAll(TAG_NAME_REG)];
62+
return [...new Set(tagMatches.map((match) => match[1]))];
63+
}
64+
4265
export async function findTagByName(db, tagName, creatorId = null) {
4366
const schema = await getTagSchema(db);
4467
const selectColumns = buildTagSelectColumns(schema);

frontend/src/components/MemoEditor/index.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Select, Option, Button, IconButton, Divider } from "@mui/joy";
2-
import { isNumber, last, uniq, uniqBy } from "lodash-es";
2+
import { isNumber, last, uniqBy } from "lodash-es";
33
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
44
import { toast } from "react-hot-toast";
55
import { useTranslation } from "react-i18next";
66
import useLocalStorage from "react-use/lib/useLocalStorage";
77
import { TAB_SPACE_WIDTH, UNKNOWN_ID, VISIBILITY_SELECTOR_ITEMS } from "@/helpers/consts";
88
import useCurrentUser from "@/hooks/useCurrentUser";
9-
import { getMatchedNodes } from "@/labs/marked";
9+
import { getMatchedTagNames } from "@/labs/marked";
1010
import { useGlobalStore, useMemoStore, useResourceStore, useTagStore } from "@/store/module";
1111
import { useUserV1Store } from "@/store/v1";
1212
import { Resource } from "@/types/proto/api/v2/resource_service";
@@ -342,8 +342,7 @@ const MemoEditor = (props: Props) => {
342342
}
343343

344344
// Upsert tag with the content.
345-
const matchedNodes = getMatchedNodes(content);
346-
const tagNameList = uniq(matchedNodes.filter((node) => node.parserName === "tag").map((node) => node.matchedContent.slice(1)));
345+
const tagNameList = getMatchedTagNames(content);
347346
for (const tagName of tagNameList) {
348347
try {
349348
await tagStore.upsertTag(tagName);

frontend/src/components/MemoList.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import { useParams } from "react-router-dom";
44
import MemoFilter from "@/components/MemoFilter";
55
import MemoDetailModal from "@/components/MemoDetailModal";
66
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
7-
import { getTimeStampByDate } from "@/helpers/datetime";
87
import useCurrentUser from "@/hooks/useCurrentUser";
9-
import { TAG_REG } from "@/labs/marked/parser";
108
import { useFilterStore, useGlobalStore, useMemoStore } from "@/store/module";
119
import { extractUsernameFromName } from "@/store/v1";
1210
import { useTranslate } from "@/utils/i18n";
@@ -23,8 +21,7 @@ const MemoList: React.FC = () => {
2321
const { loadingStatus, memos } = memoStore.state;
2422
const systemStatus = globalStore.state.systemStatus;
2523
const user = useCurrentUser();
26-
const { tag: tagQuery, duration, text: textQuery, visibility } = filter;
27-
const showMemoFilter = Boolean(tagQuery || (duration && duration.from < duration.to) || textQuery || visibility);
24+
const { tag: tagQuery, duration, text: textQuery } = filter;
2825
const username = params.username || extractUsernameFromName(user.name);
2926

3027
const fetchMoreRef = useRef<HTMLSpanElement>(null);

frontend/src/labs/marked/index.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,15 @@ export const getMatchedNodes = (markdownStr: string): MatchedNode[] => {
144144

145145
return matchedNodeList;
146146
};
147+
148+
export const getMatchedTagNames = (markdownStr: string): string[] => {
149+
const tagNameSet = new Set<string>();
150+
151+
for (const node of getMatchedNodes(markdownStr)) {
152+
if (node.parserName === "tag") {
153+
tagNameSet.add(node.matchedContent.slice(1));
154+
}
155+
}
156+
157+
return Array.from(tagNameSet);
158+
};

frontend/src/pages/Explore.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import MemoDetailModal from "@/components/MemoDetailModal";
66
import MemoFilter from "@/components/MemoFilter";
77
import MobileHeader from "@/components/MobileHeader";
88
import { DEFAULT_MEMO_LIMIT } from "@/helpers/consts";
9-
import { TAG_REG } from "@/labs/marked/parser";
9+
import { getMatchedTagNames } from "@/labs/marked";
1010
import { useFilterStore, useMemoStore } from "@/store/module";
1111
import { useTranslate } from "@/utils/i18n";
1212

@@ -27,8 +27,7 @@ const Explore = () => {
2727

2828
if (tagQuery) {
2929
const tagsSet = new Set<string>();
30-
for (const t of Array.from(memo.content.match(new RegExp(TAG_REG, "g")) ?? [])) {
31-
const tag = t.replace(TAG_REG, "$1").trim();
30+
for (const tag of getMatchedTagNames(memo.content)) {
3231
const items = tag.split("/");
3332
let temp = "";
3433
for (const i of items) {

0 commit comments

Comments
 (0)