[Question]
  [
Your challenge is to take input as a line of text and output it like this.
[![rainbow image](https://i.stack.imgur.com/JzZCj.png)](https://i.stack.imgur.com/JzZCj.png)
## Input / output
The input will be a string that contains only printable ASCII characters. The first or last characters will never be spaces, and there will never be two spaces in a row. It will always be at least two characters long.
Your output should be the same string, converted to rainbow colors as will be described below. The output may be in image form (saved to a file or somehow otherwise made available), or it may simply display the result on the screen (as the reference implementation below does).
## Conversion
To determine what color each letter in the string should become, use the following algorithm. Note that *each letter is its own individual color*. **This is not a gradient!**
* If this character is a space:
	+ ... it doesn't matter, because spaces can't really... have a color anyway. Simply output a space.
* Otherwise:
	+ Let `i` = the index of this character in the string (0-based, so for the very first letter, this is `0`), not counting spaces. For example, in the string `foo bar`, this value would be `4` for the `a`. In other words, this is how many non-spaces have been encountered so far.
	+ Let `n` = the number of non-spaces in the string.
	+ The color of this letter can now be expressed, in the [HSL cylindrical-coordinate system](https://en.wikipedia.org/wiki/HSL_and_HSV), as [hue=(`i`/`n`)\*360°, saturation=100%, lightness=50%].
Note that these directions imply that the output for `foo` and `f oo` should be exactly the same, except for an added space after the `f`. That is, all the letters should retain the same colors.
Further rules for the conversion process are described below, in the **Rules** section.
## Reference implementation
This is written in JavaScript, and you can try it by pressing the "Run code snippet" button.
```
window.addEventListener('load', function() {
    addRainbow('Your challenge is to take input as a line of text and ' +
        'output it like this.');
});
// append this text rainbow-ified to the argument (document.body by default)
function addRainbow(text, el) {
    (el || document.body).appendChild(makeRainbow(text));
}
// returns a <div> that contains the text in a rainbow font
function makeRainbow(text) {
    var div = document.createElement('div');
    var letterCount = text.replace(/ /g, '').length, spaceCount = 0;
    text.split('').forEach(function(letter, idx) {
        if (letter == ' ') ++spaceCount;
        div.appendChild(makeLetter(letter, (idx - spaceCount) / letterCount));
    });
    return div;
}
// returns a <span> that contains the letter in the specified color
function makeLetter(letter, hue) {
    hue = Math.floor(hue * 360);
    var span = document.createElement('span');
    span.appendChild(document.createTextNode(letter));
    span.style.color = 'hsl(' + hue + ', 100%, 50%)';
    return span;
}
```
## Rules
* When computing the Hue value of a letter, you will almost certainly get a decimal (non-integer) number. You may round this to the nearest integer, floor it, take the ceiling, or simply not round at all.
* The font size must be readable. Here, this is defined as a 10pt size font or greater.
* You may use a fixed-width canvas or "drawing area" to output the text, but it *must* be able to fit the example given in the very first sentence of this post.
* Scoring is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest code in bytes will win.
  
[Answer]
# [Perl 5.28.1 (webperl)](https://www.perl.org/) + `-p`, 88 bytes
```
@c=unpack C35,"..........vR../012.3-'!..9]........";s|\S|.[38;5;$c[@c*$i++/y/!-~//]m$&|g
```
[Try it online!](https://dom111.github.io/code-sandbox/#eyJsYW5nIjoid2VicGVybC01LjI4LjEiLCJjb2RlIjoiMDAwMDAwMDA6IDQwNjMgM2Q3NSA2ZTcwIDYxNjMgNmIyMCA0MzMzIDM1MmMgMjIwOSAgQGM9dW5wYWNrIEMzNSxcIi5cbjAwMDAwMDEwOiBjNGNhIGQwZDYgZGMwYiBlMmJlIDlhNzYgNTIwYSAyZTJmIDMwMzEgIC4uLi4uLi4uLnZSLi4vMDFcbjAwMDAwMDIwOiAzMjBlIDMzMmQgMjcyMSAxYjE1IDM5NWQgODFhNSBhYWM5IGM4YzcgIDIuMy0nIS4uOV0uLi4uLi5cbjAwMDAwMDMwOiBjNmM1IDIyM2IgNzM3YyA1YzUzIDdjMWIgNWIzMyAzODNiIDM1M2IgIC4uXCI7c3xcXFN8LlszODs1O1xuMDAwMDAwNDA6IDI0NjMgNWI0MCA2MzJhIDI0NjkgMmIyYiAyZjc5IDJmMjEgMmQ3ZSAgJGNbQGMqJGkrKy95LyEtflxuMDAwMDAwNTA6IDJmMmYgNWQ2ZCAyNDI2IDdjNjcgICAgICAgICAgICAgICAgICAgICAgLy9dbSQmfGciLCJhcmdzIjoiLXAiLCJpbnB1dCI6IllvdXIgY2hhbGxlbmdlIGlzIHRvIHRha2UgaW5wdXQgYXMgYSBsaW5lIG9mIHRleHQgYW5kIG91dHB1dCBpdCBsaWtlIHRoaXMuIn0=)
## Explanation
This script uses an approximation of the colours available to terminal (256 maximum) currently only including a few colour points selected from [this list](https://gist.github.com/dom111/1d3f73081a9a3c8d1d16), so it is likely not to spec, but this was fun anyway! I filtered the list to only show colours with `S` and `L` values of `100%` and `50%` respectively, then sorted by hue, packed the numbers into a string and select the colours from that list.
This implementation includes non-printable characters! Stole [@edc65](https://codegolf.stackexchange.com/users/21348/edc65)'s idea of only replacing `\S` instead of `.`, simple, but clever!
[Answer]
# Python 2: 240 using PIL and colorsys lib
```
import PIL,colorsys as c
s=input()
u,a=len(s),255
g=Image.new('RGB',(u*6,13),(a,)*3)
[ImageDraw.Draw(g).text((j*6,0),s[j],fill=tuple(int(h*a)for h in c.hls_to_rgb(1.*(j-s[:j].count(' '))/(u-s.count(' ')),.5,1)))for j in range(u)]
g.show()
```
Example output:
[![Output rainbow text example](https://i.stack.imgur.com/1yzlz.png)](https://i.stack.imgur.com/1yzlz.png)
[![test with spaces](https://i.stack.imgur.com/iqwiL.png)](https://i.stack.imgur.com/iqwiL.png)
Thanks to @agtoever and @Trang Oul for some golfing tips, and for @Mauris for pointing out the spaces requirement.
To add a true type fonts, font size control, including horizontal offset and color change based on length.
```
import PIL as P,colorsys as c
s=input()
u=len(s)
a=255
fs=25
f=P.ImageFont.truetype("a.ttf",fs)
sza=f.getsize(s)
oa=f.getoffset(s)
g=P.Image.new('RGB',(sza[0]+fs,2*sza[1]+oa[1]),(a,)*3)
r=fs/4
P.ImageDraw.Draw(g).text((r,0),s,fill=(0,0,0),font=f)
for j in range(u):   
 o=f.getoffset(s[j])
 sz=f.getsize(s[j])   
 r+=o[0]
 P.ImageDraw.Draw(g).text((r,0+fs),s[j],fill=tuple([int(h*a)for h in c.hls_to_rgb(1.*r/sza[0],.5,1)]),font=f)
 r+=sz[0]
g.save('a.png')
g.show()
```
The font I used is available from [here](http://www.fontsquirrel.com/fonts/MomsTypewriter?filter%5Bclassifications%5D%5B0%5D=typewriter&sort=popular):
The result is (the top is just printing the string, the one below is printing per letter):
[![typewriter](https://i.stack.imgur.com/T1QYQ.png)](https://i.stack.imgur.com/T1QYQ.png)
[Answer]
# Python 3, 131 bytes
Simular to Dom Hastings' answer but implemented in python.
The string `'|\x82\x88\x8ejF"#$%\x1f\x19\x137[\x7f~}'` was built form the list `[124,130,136,142,106,70,34,35,36,37,31,25,19,55,91,127,126,125]` is the terminal colour codes to display in order. They have been filtered so they only include colours with saturation 100% and value 50%. The list was then sorted so the correct hues were displayed first.
Takes input from stdin and returns it to stdout.
### Your terminal you are using MUST support ANSI escape codes to run this properly.
```
x=input();u=u'|\82\88\8ejF"#$%\1f\19\137[\7f~}';j=0
for i in x:print('\033[38;5;%dm%s'%(ord(u[j*18//len(x.replace(" ", ""))]),i),end="");j+=i!=" "
```
Or shortened version with literal byte characters (Didn't paste properly):
```
x=input();u='|<82><88><8E>jF"#$%^_^Y^S7[^?~}';j=0
for i in x:print('ESC[38;5;%dm%s'%(ord(u[(j*18)//len(x.replace(" ", ""))]),i),end="");j+=i!=" "
```
Literal hexdump:
```
783d696e70757428293b753d277c82888e6a46222324251f1913375b7f7e7d273b6a3d300a666f72206920696e20783a7072696e7428271b5b33383b353b25646d25732725286f726428755b286a2a3138292f2f6c656e28782e7265706c616365282220222c20222229295d292c69292c656e643d2222293b6a2b3d69213d2220220a
```
Thanks @swstephe for saving 9 bytes (and also making me notice my byte counting was ever so slightly very wrong)!
[Answer]
# JavaScript (ES6), 114 ~~117 125~~
*Edit2* 3 bytes saved thx @Dom Hastings
*Edit* Invalid HTML, but working anyway. 
Usual note: test running the snippet on an EcmaScript 6 compliant browser (notably not Chrome not MSIE. I tested on Firefox)
```
F=s=>document.write(s.replace(/\S/g,c=>`<b style=color:hsl(${i++/s.replace(/ /g,'').length*360},100%,50%>`+c,i=0))
```
```
<input value='Your challenge is to take input as a line of text and output it like this.' id=I size=100>
<button onclick='F(I.value)'>-></button>
```
[Answer]
# PHP, 165 bytes
Run with input as the parameter "s"
The HTML is invalid but it should render in all major browsers (tested in Chrome and Firefox)
```
<?php $n=preg_match_all("/[^ ]/",$q=$_GET['s']);for($i=$j=0;$j<strlen($q);$j++){if(" "!=$s=$q[$j])$i+=360;echo"<a style='color:hsl(".floor($i/$n).",100%,50%)'>".$s;}
```
[Answer]
# PHP 4.1, ~~112~~ ~~103~~ 102 bytes
I've used [@DankMemes' answer](https://codegolf.stackexchange.com/a/55134/14732) as a starting point. From there on, I've implemented a **ton** of changes, to the point that the code is different.
The implementation is similar, the code is totally different.
```
foreach(str_split($s)as$c)echo"<a style=color:hsl(",((" "^$c?$i+=360:$i)/strlen($s))|0,",100%,50%>$c";
```
To use it, simply set a value on a SESSION/GET/POST/COOKIE with the name `s`.
Result of running this function, on the test sentence:
```
<a style=color:hsl(4,100%,50%>Y<a style=color:hsl(9,100%,50%>o<a style=color:hsl(14,100%,50%>u<a style=color:hsl(19,100%,50%>r<a style=color:hsl(24,100%,50%> <a style=color:hsl(29,100%,50%>c<a style=color:hsl(34,100%,50%>h<a style=color:hsl(38,100%,50%>a<a style=color:hsl(43,100%,50%>l<a style=color:hsl(48,100%,50%>l<a style=color:hsl(53,100%,50%>e<a style=color:hsl(58,100%,50%>n<a style=color:hsl(63,100%,50%>g<a style=color:hsl(68,100%,50%>e<a style=color:hsl(72,100%,50%> <a style=color:hsl(77,100%,50%>i<a style=color:hsl(82,100%,50%>s<a style=color:hsl(87,100%,50%> <a style=color:hsl(92,100%,50%>t<a style=color:hsl(97,100%,50%>o<a style=color:hsl(102,100%,50%> <a style=color:hsl(107,100%,50%>t<a style=color:hsl(111,100%,50%>a<a style=color:hsl(116,100%,50%>k<a style=color:hsl(121,100%,50%>e<a style=color:hsl(126,100%,50%> <a style=color:hsl(131,100%,50%>i<a style=color:hsl(136,100%,50%>n<a style=color:hsl(141,100%,50%>p<a style=color:hsl(145,100%,50%>u<a style=color:hsl(150,100%,50%>t<a style=color:hsl(155,100%,50%> <a style=color:hsl(160,100%,50%>a<a style=color:hsl(165,100%,50%>s<a style=color:hsl(170,100%,50%> <a style=color:hsl(175,100%,50%>a<a style=color:hsl(180,100%,50%> <a style=color:hsl(184,100%,50%>l<a style=color:hsl(189,100%,50%>i<a style=color:hsl(194,100%,50%>n<a style=color:hsl(199,100%,50%>e<a style=color:hsl(204,100%,50%> <a style=color:hsl(209,100%,50%>o<a style=color:hsl(214,100%,50%>f<a style=color:hsl(218,100%,50%> <a style=color:hsl(223,100%,50%>t<a style=color:hsl(228,100%,50%>e<a style=color:hsl(233,100%,50%>x<a style=color:hsl(238,100%,50%>t<a style=color:hsl(243,100%,50%> <a style=color:hsl(248,100%,50%>a<a style=color:hsl(252,100%,50%>n<a style=color:hsl(257,100%,50%>d<a style=color:hsl(262,100%,50%> <a style=color:hsl(267,100%,50%>o<a style=color:hsl(272,100%,50%>u<a style=color:hsl(277,100%,50%>t<a style=color:hsl(282,100%,50%>p<a style=color:hsl(287,100%,50%>u<a style=color:hsl(291,100%,50%>t<a style=color:hsl(296,100%,50%> <a style=color:hsl(301,100%,50%>i<a style=color:hsl(306,100%,50%>t<a style=color:hsl(311,100%,50%> <a style=color:hsl(316,100%,50%>l<a style=color:hsl(321,100%,50%>i<a style=color:hsl(325,100%,50%>k<a style=color:hsl(330,100%,50%>e<a style=color:hsl(335,100%,50%> <a style=color:hsl(340,100%,50%>t<a style=color:hsl(345,100%,50%>h<a style=color:hsl(350,100%,50%>i<a style=color:hsl(355,100%,50%>s<a style=color:hsl(360,100%,50%>. 
```
]