Oddly enough, I did a rainbow as an exercise recently. I don't know how much it will help, but here it is:
shader_type canvas_item;
vec3 hsb2rgb(vec3 c) {
vec3 t = vec3(0.0, 4.0, 2.0);
vec3 rgb = mod(c.x * 6.0 + t, 6.0);
rgb = clamp(abs(rgb - 3.0) - 1.0, 0.0, 1.0);
rgb = rgb*rgb*(3.0-2.0*rgb);
return c.z * mix(vec3(1.0), rgb, c.y);
}
vec4 rainbow(vec2 uv) {
vec3 color = vec3(1.0);
float x = uv.x;
vec2 c1 = vec2(0.5, -0.2);
vec2 c2 = vec2(0.5, 0.2);
float r2 = 0.7 * 0.7;
float y2 = sqrt(r2 - pow(x - c1.x, 2)) + c1.y;
float y1 = sqrt(r2 - pow(x - c2.x, 2)) + c2.y;
y1 = 1.0 - y1;
y2 = 1.0 - y2;
float hue = 1.0;
vec3 bow = vec3(1.0);
if (uv.y > y1 && uv.y < y2)
{
hue = (uv.y - y2) * 0.9 / 0.4 - 0.17;
bow.r = 0.0;
bow.g = 0.0;
bow.b = 0.0;
float t1 = 1.0;
float t2 = 1.0;
bow = hsb2rgb(vec3(hue, t1, t2));
color = bow;
return vec4(color * 0.2 + bow * 0.8, 1.0);
} else
return vec4(0.0, 0.5, 1.0, 1.0);
return vec4(color, 1.0);
}
void fragment() {
COLOR = rainbow(UV);
}

Edit: Removed some useless cruft.