azureurlazure-devopsazure-devops-wiki

What is the URL for New Page in Azure DevOps Wiki? / How to bookmark New Page?


Is there a URL for New Page in Azure DevOps Wiki?

Specifically one where I can specify the path that it will create the new page under/in.

I know that if you wanted to bookmark the link to view a specific page you'd usually need to know the page ID, E.G. 22 in this link:

https://dev.azure.com/acmecorp/ACME%20Corp/_wiki/wikis/ACME-Corp.wiki/22/Backups-Restores

However there is a "secret link" you can use to specify the path instead, when the page ID is unknown:

https://dev.azure.com/acmecorp/ACME%20Corp/_wiki/wikis/ACME-Corp.wiki?pagePath=/Home/Technical/Important/Backups%20%26%20Restores

And to edit a page at a specified path it's:

https://dev.azure.com/acmecorp/ACME%20Corp/_wiki/wikis/ACME-Corp.wiki?wikiVersion=GBwikiMaster&_a=edit&pagePath=/Home/Technical/Important/Backups%20%26%20Restores

I tried modifying that last URL from &_a=edit to &_a=new and &a_=add but neither worked.

How can I link to New Page / New Subpage for a specified path?

When I click New Page from within DevOps Wiki, the URL in the address bar does not change.

This is for a larger project that automatically builds Sphinx Docs () from an Azure DevOps Wiki. I'd like the ability to have a New button in Sphinx. Currently I've managed to add "View on Wiki" and "Edit on Wiki" buttons to each page, along with a few more that are not Wiki-related - and I'm looking to add "New page" to it... but essentially my question boils down: what is the URL for New page at a specified path?

Here's what each page looks like in Sphinx:

I checked the event listeners on the New Page button in DevOps Wiki but from what I saw it links to an empty function called we()

If you're interested: I'm using to auto-build Sphinx from the Wiki each time an edit is made, and the HTML of each page gets customised by some scripts I've written, largely using .


Solution

  • Installation

    Here is a client-side solution (no API needed).

    Install the Tampermonkey browser extension, then create a new userscript as below:

    // ==UserScript==
    // @name         Azure DevOps Wiki - New Page
    // @namespace    http://stackoverflow.com
    // @version      0.4.4
    // @description  This userscript is required in order for the New Page bookmark to work, since there is no direct URL for New Page
    // @author       Public domain
    // @match        https://dev.azure.com/*/*/_wiki/wikis/*.wiki?wikiVersion=*&_a=*
    // @icon         https://www.google.com/s2/favicons?sz=64&domain=azure.com
    // @grant        none
    // @require      https://cdn.jsdelivr.net/gh/jquery/jquery/dist/jquery.min.js
    // ==/UserScript==
    /* global $ */
    
    (function() {
        'use strict';
    
        // TODO: Remove the setTimeout's by using setInterval's to wait for the required elements to load
    
        // Continuation point
        if(localStorage.getItem('newPage') === '1') {
            console.log('📫 Received a request to create a new page!');
    
            window.setTimeout(function(){
    
                // We can't simply click the New Page button at the bottom of the nav tree, since this would create a page ALONGSIDE the current page, not BENEATH it
                // Instead, click the context menu icon next to the current page in the nav tree
                $('table[role="treegrid"] tr[aria-current="page"] button[aria-haspopup="true"]').eq(0).click();
    
                // Then click Add Sub-page
                $('div.bolt-callout #__bolt-addSubPage-text').eq(0).click();
                console.log('📤 Forwarded the request to create a new page!');
    
                // Specify the default content
                window.setTimeout(function() {
    
                    // For some reason we can't get this to work with a jQuery $ selector
                    var txt = document.querySelector('textarea');
                    txt.innerHTML = `[:open_file_folder: *Up a folder*](${localStorage.getItem('pagePath')})
    
    [[_TOC_]]
    
    ---
    
    # Preface
    
    - `;
    
                    // This does not update the preview pane
                    // We tried to dispatch keydown/keypress/keyup events to trigger the event handlers but the preview pane still did not update
                    // Also MS puts the focus in the Title textbox - which if the user enters anything in to, would clear the default content (since the preview pane is blank)
                    // Instead we will move the caret to the end and then click the code button, then click it again to get rid of the code marks (``)
                    txt.focus();
                    txt.selectionStart = txt.value.length - 1;
                    txt.selectionEnd = txt.value.length;
                    $('button[data-command-key="code-menu-item"]').eq(0).click();
                    $('button[data-command-key="code-menu-item"]').eq(0).click();
    
                    // Finally, put the focus back where it started in the Title textbox
                    $('input.title-m').eq(0).focus();
    
                    // Quit
                    localStorage.setItem('newPage', 0);
                    localStorage.setItem('pagePath', null);
                    console.log('✅ Fulfilled the request to create a new page!');
                }, 500); // ms
            }, 1500); // ms
    
            return;
        }
    
        // Entry point
        if(window.location.href.indexOf('&_a=new') >= 0) {
            console.log('📮 Sent a request to create a new page!');
            localStorage.setItem('newPage', 1);
            localStorage.setItem('pagePath', window.location.href.split('&pagePath=')[1].replace(/%20/g, '-').replace(/%252D/g, '%2D')); // Replacing %252A with * is not needed
            window.location.href = window.location.href.replace('&_a=new', '&_a=edit');
        }
    })();
    

    Usage

    You can now use a link like below as a bookmark. Check your own edit link and replace the various parts of the URL. &pagePath= is the path to the page you want to create a sub-page under.

    https://dev.azure.com/acmecorp/ACME%20Corp/_wiki/wikis/ACME-Corp.wiki?wikiVersion=GBwikiMaster&_a=new&pagePath=/Some/Path/To/Your/Page

    Explanation

    Microsoft do a good job of trying to strip out invalid query string variable keys (but not invalid variable values) and hash anchors from URLs but this method works, by sending an invalid query string of &_a=new, intercepting this, setting a local storage var (like a cookie), redirecting to the edit page, and catching the local storage var.

    From there, the script can't simply click New Page since this will create a page alongside the current page, not beneath it. Instead it opens the actions menu for the currently selected page in the left nav tree, and clicks Add Sub-page.

    After that it fills in some default content, including a link to the folder that's up a dir using the pagePath specified in the bookmark link (during the script's execution, the page will be redirected and this variable will be stripped from the address bar, so we save it in another local storage var).

    Finally it clicks the insert code block button at the end of the content to force the preview pane to update and to make it so typing a title doesn't clear the default content. Then it clicks it once more to get rid of the `` marks.

    Troubleshooting

    If there is a console message saying that the request was forwarded but the New Page screen does not appear, try increasing the timeout from 1500 milliseconds.

    If there is a console message saying that the request was fulfilled but the default content doesn't appear in the text box, try increasing the other timeout from 500 milliseconds.