Using web resources, you can include JavaScript and CSS resources into specific contexts. 

You can read more about web resource modules for Bitbucket. You could use a web resource on the Pull Request view page or Create a New Repository page.

Setup

Web resources need to be loaded from a plugin or a specified directory. You can provide a list of directories using the system property plugin.resource.directories. It makes sense to use the default scripts directory, which is automatically created in your application home directory.

If you do use the scripts directory, you can modify your setenv.sh(or.bat) script with the following code:

JVM_REQUIRED_ARGS='-Dplugin.resource.directories=/app/home/scripts -Dother.properties...'
CSS

You can provide multiple comma-separated directories. Then, the resource loader searches the directories, in order, until it finds a matching file.

Reloading

There is no negative performance impact to adding resources. When the resource is found, it is cached.

This means that you cannot change your resource and have it instantly reloaded. After changing the resource, you need to edit the web-resource item in the UI, update, and then hard refresh in your browser.

This is not the case when running with -Datlassian.dev.mode=true, in which case reloading should work. This means you should work on your web resources in a dev environment, then transfer them to your production environment when you are finished.


Modifying CSS

This is an example of changing the Pull Request titles to red with CSS.

  1. Go to Administration > Script Fragments > Install Web Resource.
  2. Configure the form to look like this:
  3. Create the resource: red-pullrequest-titles.css

    Clicking Preview or Update gives you an error at this point.

    1. In a text editor, create this file under one of the directories you have defined in plugin.resource.directories.

      If you use the script directory, this is <app.home>/scripts.

    2. Enter the following contents:

      h1, h2, h3, h4, h5, h6 {
          color: red !important
      }
      


    3. Return to the page and click Update.

      If you still get an error, make sure the file name and provided Resource name is the same. 

Result: When accessing the pull request page, the titles will be red-colored.

Injecting JavaScript into a specific context

You can inject JavaScript into a specific context. The example below shows how to log to the console when accessing admin pages. 

  1. Copy and paste the snippet below in a text editor.

    console.log("Javascript in admin page context");

  2. Save the text editor file as console-log.js under one of the directories you have defined as a resource directory in plugin.resource.directories
  3. Go to Admin > Script Fragments > Install Web Resource
  4. Configure the form to look like this:
    New version
  5. Click Preview to see your valid result, which you can see in the above image.

    If you receive an error, make sure the file name and provided Resource name are the same. 

Result: The console shows the message JavaScript in admin page context after accessing an admin page.

New version

A more complicated example would be to wire up the buttons of a custom dialog using a Javascript resource.

Restrict public access permission

This example restricts the Project and Repository Public Access Permission settings to global and system administrators only and disables it for project and repository administrators by injecting JavaScript.

By using this permission control, you can prevent accidental policy violations.

  1. Copy and paste the snippet below in a text editor.

    $(() => {
        const publicAccess = document.getElementById("public-access-allowed")
    
        if (!publicAccess) {
            return
        }
    
        require(['bitbucket/util/state'], function(state) {
            publicAccess.disabled = !state.getCurrentUser().isAdmin
        })
    })
    

  2. Save the text editor file as disable-public-access.js under one of the directories you have defined as a resource directory in plugin.resource.directories
  3. Go to Admin > Script Fragments > Install Web Resource
  4. Set the required context using the Context(s) field. The required contexts for project and repository permission pages are listed below:
    1. Project - bitbucket.page.project.permissions 
    2. Repository - bitbucket.page.repository.permissions 
  5. Define a key.
    You can set as disable-public-access as an example for the Key field.
  6. Set the value disable-public-access.js for the Resources field.
  7. Your form should look like this:
  8. Click on the Preview button to validate the fragment. If you receive an error, make sure the file name and the provided Resource name are identical. 

Result: When a Project or Repository Admin tries to edit the public access permission, the field will be disabled.


In addition to this example, you can add a custom listener that also rejects any attempts to change this setting through the REST API or Plugin Java API.

  1. Go to Global Administration > Listeners > Custom Listener
  2. Set the Event field to where the listener will be added.
    1. Project - ProjectModificationRequestedEvent
    2. Repository - RepositoryModificationRequestedEvent
  3. Set the script below for the Script field.

    package examples.bitbucket.listener
    
    import com.atlassian.bitbucket.event.project.ProjectModificationRequestedEvent
    import com.atlassian.bitbucket.event.repository.RepositoryModificationRequestedEvent
    import com.atlassian.bitbucket.permission.Permission
    import com.atlassian.bitbucket.permission.PermissionService
    import com.atlassian.sal.api.component.ComponentLocator
    
    def permissionService = ComponentLocator.getComponent(PermissionService)
    
    def currentEvent
    if (event instanceof ProjectModificationRequestedEvent) {
        currentEvent = event as ProjectModificationRequestedEvent
    } else if (event instanceof RepositoryModificationRequestedEvent) {
        currentEvent = event as RepositoryModificationRequestedEvent
    }
    
    def user = currentEvent.user
    def isGlobalAdmin = permissionService.hasGlobalPermission(user, Permission.ADMIN)
    def hasPublicAccessChanged = currentEvent.oldValue.public != currentEvent.newValue.public
    
    if (!isGlobalAdmin && hasPublicAccessChanged) {
        currentEvent.cancel("Only Global Administrators are allowed to change Public Access.")
    }
    

Result: When a project or repository administrator tries to edit the public access permission, an error message is displayed:


This error message is only shown if the fragment is disabled and the listener is enabledIf your JavaScript script fragment is enabled, the public access field is disabled. Therefore, you won't be able to click on the public access field. We recommend using the fragment and listener together to cover the restriction through UI, the REST API, and Plugin Java API.