···11+import { describe, expect, it } from 'vitest';
22+import { editLinkFor, editRkeyFromSearch } from './edit-link';
33+44+describe( 'editLinkFor', () => {
55+ it( 'builds the editor edit URL for an rkey', () => {
66+ expect( editLinkFor( '3kabc123' ) ).toBe( '/editor?edit=3kabc123' );
77+ } );
88+} );
99+1010+describe( 'editRkeyFromSearch', () => {
1111+ it( 'reads the rkey from the edit param', () => {
1212+ expect( editRkeyFromSearch( '?edit=3kabc123' ) ).toBe( '3kabc123' );
1313+ } );
1414+1515+ it( 'returns null when the param is absent', () => {
1616+ expect( editRkeyFromSearch( '?foo=bar' ) ).toBeNull();
1717+ expect( editRkeyFromSearch( '' ) ).toBeNull();
1818+ } );
1919+2020+ it( 'returns null when the param is present but empty', () => {
2121+ expect( editRkeyFromSearch( '?edit=' ) ).toBeNull();
2222+ } );
2323+} );
+18
src/lib/editor/edit-link.ts
···11+/**
22+ * The dashboard→editor "edit this article" link, and the editor-side parser for
33+ * it. Kept together so the `?edit=` param name has a single source of truth.
44+ * `rkey` uniquely identifies a document within the writer's repo, so it is all
55+ * the editor needs to re-fetch the article on load.
66+ */
77+const EDIT_PARAM = 'edit';
88+99+/** The editor URL that opens an existing article for editing. */
1010+export function editLinkFor( rkey: string ): string {
1111+ return `/editor?${ EDIT_PARAM }=${ rkey }`;
1212+}
1313+1414+/** The rkey to edit, parsed from a URL search string (e.g. `window.location.search`). Null when absent or empty. */
1515+export function editRkeyFromSearch( search: string ): string | null {
1616+ const rkey = new URLSearchParams( search ).get( EDIT_PARAM );
1717+ return rkey && rkey.length > 0 ? rkey : null;
1818+}