/
githubmirror
/
zulip
Обзор
Документация
Войти
/
githubmirror
/
zulip
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
web/src/hash_parser.ts
198 строк
6 KB
Anders Kaseorg
eslint: Fix unicorn/prefer-split-limit.
29 июл 2026, 02:35
29 июл 2026, 02:35
2069019
Код
Авторство
О чём код?
// See the Zulip URL spec at https://zulip.com/api/zulip-urls import {type NarrowTerm, narrow_operator_schema} from "./state_data.ts"; import * as util from "./util.ts"; export function get_hash_category(hash?: string): string { // given "#channels/subscribed", returns "channels" return hash ? hash.replace(/^#/, "").split(/\//, 1)[0]! : ""; } export function get_hash_section(hash?: string): string { // given "#settings/profile", returns "profile" // given '#channels/5/social", returns "5" if (!hash) { return ""; } const parts = hash.replace(/\/$/, "").split(/\//); return parts[1] ?? ""; } function get_nth_hash_section(hash: string, n: number): string { // given "#settings/profile" and n=1, returns "profile" // given '#channels/5/social" and n=2, returns "social" const parts = hash.replace(/\/$/, "").split(/\//); return parts.at(n) ?? ""; } export function get_current_nth_hash_section(n: number): string { return get_nth_hash_section(window.location.hash, n); } export function get_current_hash_category(): string { return get_hash_category(window.location.hash); } export function get_current_hash_section(): string { return get_hash_section(window.location.hash); } export function is_same_server_message_link(url: string): boolean { // A same server message link always has category `narrow`, // section `channel` or `dm`, and ends with `/near/<message_id>`, // where <message_id> is a sequence of digits. return ( get_hash_category(url) === "narrow" && (get_hash_section(url) === "channel" || get_hash_section(url) === "dm") && get_nth_hash_section(url, -2) === "near" && util.is_numeric_string(get_nth_hash_section(url, -1)) ); } export function is_overlay_hash(hash: string | undefined): boolean { // Hash changes within this list are overlays and should not unnarrow (etc.) const overlay_list = [ // In 2024, stream was renamed to channel in the Zulip API and UI. // Because pre-change Welcome Bot and Notification Bot messages // included links to "/#streams/all" and "/#streams/new", we'll // need to support "streams" as an overlay hash as an alias for // "channels" permanently. "streams", "channels", "drafts", "groups", "settings", "organization", "invite", "keyboard-shortcuts", "message-formatting", "search-operators", "about-zulip", "scheduled", "reminders", "user", ]; const main_hash = get_hash_category(hash); return overlay_list.includes(main_hash); } // this finds the stream that is actively open in the settings and focused in // the left side. export function is_editing_stream(desired_stream_id: number): boolean { const hash_components = window.location.hash.slice(1).split(/\//); if (hash_components[0] !== "channels") { return false; } if (!hash_components[2]) { return false; } // if the string casted to a number is valid, and another component // after exists then it's a stream name/id pair. const stream_id = Number.parseFloat(hash_components[1]!); return stream_id === desired_stream_id; } export function is_create_new_stream_narrow(): boolean { return window.location.hash === "#channels/new"; } // This checks whether the user is in the stream settings menu // and is opening the 'Subscribers' tab on the right panel. export function is_subscribers_section_opened_for_stream(): boolean { const hash_components = window.location.hash.slice(1).split(/\//); if (hash_components[0] !== "channels") { return false; } if (!hash_components[3]) { return false; } return hash_components[3] === "subscribers"; } export function is_in_specified_hash_category(hash_categories: string[]): boolean { const main_hash = get_hash_category(window.location.hash); return hash_categories.includes(main_hash); } export function is_an_allowed_web_public_narrow( operator: NarrowTerm["operator"], operand: NarrowTerm["operand"], ): boolean { if (operator === "is" && operand === "resolved") { return true; } return allowed_web_public_narrow_operators.includes(operator); } export const allowed_web_public_narrow_operators = [ "channels", "channel", // This is sent as an anchor to the server rather // than a narrow operator, but is part of the fragment. "date", "streams", "stream", "topic", "sender", "has", "search", "near", "id", "with", ]; export function is_spectator_compatible(hash: string): boolean { // Defines which views are supported for spectators. // This implementation should agree with the similar function in zerver/lib/narrow.py. const web_public_allowed_hashes = [ "", // full #narrow hash handled in filter.is_spectator_compatible "narrow", // TODO/compatibility: #recent_topics was renamed to #recent // in 2022. We should support the old URL fragment at least // until one cannot directly upgrade from Zulip 5.x. "recent_topics", "recent", "keyboard-shortcuts", "message-formatting", "search-operators", // TODO/compatibility: #all_messages was renamed to #feed // in 2024. We should support the old URL fragment at least // until one cannot directly upgrade from Zulip 8.x. "all_messages", "feed", "about-zulip", "topics", ]; const main_hash = get_hash_category(hash); if (main_hash === "narrow") { const hash_components = hash .split(/\//) .filter((hash_component) => hash_component !== "#narrow"); for (let i = 0; i < hash_components.length; i += 2) { const hash_section = hash_components[i]!.replace(/^-/, ""); const second_hash_section = hash_components[i + 1]!; const operator = narrow_operator_schema.safeParse(hash_section); if ( !operator.success || !is_an_allowed_web_public_narrow(operator.data, second_hash_section) ) { return false; } } return true; } return web_public_allowed_hashes.includes(main_hash); }