Skip to content

Commit

Permalink
Adddons: allow injecting an "always live" JavaScript file (#11758)
Browse files Browse the repository at this point in the history
We talked about giving users a way to inject a JavaScript file they
control using our Cloudflare Worker infrastructure to allow them
manipulate frozen documentations.

This could be used in different ways to fix bugs or add features to a
particular frozen set of docs or even to all the versions. The user can
make usage of API data to filter by version or not
(e.g. `if (versions.current == "v3.0") { .. do something ...} `)

The script could live in Read the Docs itself using a relative URL, or
outside it, using an absolute URL.


### Example using Sphinx

1. [Tell Sphinx to include `static`
folder](https://github.com/readthedocs/test-builds/blob/full-feature/docs/conf.py#L25)
2. [Include a `readthedocs.js` file in your
project](https://github.com/readthedocs/test-builds/blob/full-feature/docs/static/readthedocs.js)
3. Make `AddonsConfig.userjsfile_src` to be
`/en/full-feature/readthedocs.js` from addons admin UX

The console will render the following:


![Screenshot_2024-11-11_18-13-59](https://github.com/user-attachments/assets/9fa46525-3b20-4d88-9950-f0a93a1199ab)

Related #11474
Related readthedocs/addons#431
  • Loading branch information
humitos authored Nov 18, 2024
1 parent 774de8e commit 079283b
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 0 deletions.
35 changes: 35 additions & 0 deletions readthedocs/projects/migrations/0135_addons_customscript.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.2.16 on 2024-11-13 13:34

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.before_deploy

dependencies = [
('projects', '0134_addons_load_when_embedded_notnull'),
]

operations = [
migrations.AddField(
model_name='addonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='addonsconfig',
name='customscript_src',
field=models.CharField(blank=True, help_text='URL to a JavaScript file to inject at serve time', max_length=512, null=True),
),
migrations.AddField(
model_name='historicaladdonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False, null=True),
),
migrations.AddField(
model_name='historicaladdonsconfig',
name='customscript_src',
field=models.CharField(blank=True, help_text='URL to a JavaScript file to inject at serve time', max_length=512, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-11-13 13:36

from django.db import migrations, models
from django_safemigrate import Safe


class Migration(migrations.Migration):
safe = Safe.after_deploy

dependencies = [
('projects', '0135_addons_customscript'),
]

operations = [
migrations.AlterField(
model_name='addonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False),
),
migrations.AlterField(
model_name='historicaladdonsconfig',
name='customscript_enabled',
field=models.BooleanField(default=False),
),
]
12 changes: 12 additions & 0 deletions readthedocs/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,18 @@ class AddonsConfig(TimeStampedModel):
search_enabled = models.BooleanField(default=True)
search_default_filter = models.CharField(null=True, blank=True, max_length=128)

# User JavaScript File
customscript_enabled = models.BooleanField(default=False)

# This is a user-defined file that will be injected at serve time by our
# Cloudflare Worker if defined
customscript_src = models.CharField(
max_length=512,
null=True,
blank=True,
help_text="URL to a JavaScript file to inject at serve time",
)

# Notifications
notifications_enabled = models.BooleanField(default=True)
notifications_show_on_latest = models.BooleanField(default=True)
Expand Down
4 changes: 4 additions & 0 deletions readthedocs/proxito/tests/responses/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@
"default_filter": "project:project/latest",
"filters": []
},
"customscript": {
"enabled": false,
"src": null
},
"linkpreviews": {
"enabled": false,
"root_selector": "[role=main] a.internal",
Expand Down
4 changes: 4 additions & 0 deletions readthedocs/proxito/views/hosting.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,10 @@ def _v1(self, project, version, build, filename, url, request):
# "filepath": "/docs/index.rst",
# },
},
"customscript": {
"enabled": project.addons.customscript_enabled,
"src": project.addons.customscript_src,
},
"search": {
"enabled": project.addons.search_enabled,
# TODO: figure it out where this data comes from.
Expand Down

0 comments on commit 079283b

Please sign in to comment.