Simplify the version bump process. ### Description

Simplify the version bump process.

- Use substitution hook in docs to update CDN URL.
  - In `dev` or `prerelease` versions, it will point to `dev` url
  - In `stable` versions, it will point it `vX.Y.Z` url
- Introduce a version bump script `tools/bump_version.py`.


~- Use `bump2version` to bump Python versions (continuing from #2460)~
~- Use `npm version` to bump JS versions~
~- Update `run_docker` script to use latest deployed pre-built docker image when `--pre-built` option is specified.~

### Checklists

- [x] Add new / update outdated documentation

from pyodide_test_runner import run_in_pyodide


@run_in_pyodide(packages=["numpy", "imageio"])
def test_imageio(selenium_standalone):
    import imageio
    import numpy as np

    filename = "/tmp/foo.tif"
    image_in = np.random.randint(0, 65535, size=(100, 36), dtype=np.uint16)
    imageio.imwrite(filename, image_in)
    image_out = imageio.imread(filename)
    assert image_out.shape == (100, 36)
    np.testing.assert_equal(image_in, image_out)


@run_in_pyodide(packages=["numpy", "imageio"])
def test_jpg(selenium):
    import imageio
    import numpy as np

    img = np.zeros((5, 5), dtype=np.uint8)
    imageio.imsave("img.jpg", img)
    assert (imageio.imread("img.jpg") == img).all()

from pyodide_test_runner import run_in_pyodide


@run_in_pyodide(packages=["numpy", "imageio"])
def test_imageio(selenium_standalone):
    import imageio
    import numpy as np

    filename = "/tmp/foo.tif"
    image_in = np.random.randint(0, 65535, size=(100, 36), dtype=np.uint16)
    imageio.imwrite(filename, image_in)
    image_out = imageio.imread(filename)
    assert image_out.shape == (100, 36)
    np.testing.assert_equal(image_in, image_out)


@run_in_pyodide(packages=["numpy", "imageio"])
def test_jpg(selenium):
    import imageio
    import numpy as np

    img = np.zeros((5, 5), dtype=np.uint8)
    imageio.imsave("img.jpg", img)
    assert (imageio.imread("img.jpg") == img).all()
