text:
It took me a lot of time to make this, pls like. (YouTube Comments #1)
Hold up..... this isn't trolling.

Background
These days on YouTube, comment sections are littered with such patterns:
S
St
Str
Stri
Strin
String
Strin
Stri
Str
St
S

where String is a mere placeholder and refers to any combination of characters. These patterns are usually accompanied by a It took me a lot of time to make this, pls like or something, and often the OP succeeds in amassing a number of likes.

The Task
Although you've got a great talent of accumulating upvotes on PPCG with your charming golfing skills, you're definitely not the top choice for making witty remarks or referencing memes in YouTube comment sections. Thus, your constructive comments made with deliberate thought amass a few to no 'likes' on YouTube. You want this to change. So, you resort to making the abovementioned clichéd patterns to achieve your ultimate ambition, but without wasting any time trying to manually write them.
Simply put, your task is to take a string, say s, and output 2*s.length - 1 substrings of s, delimited by a newline, so as to comply with the following pattern:
(for s = "Hello")
H
He
Hel
Hell
Hello
Hell
Hel
He
H

Input
A single string s. Input defaults of the community apply.
You can assume that the input string will only contain printable ASCII characters.

Output
Several lines separated by a newline, constituting an appropriate pattern as explained above. Output defaults of the community apply.
Leading and trailing blank (containing no characters or characters that cannot be seen, like a space) lines in the output are permitted.

Test Case
A multi-word test case:
Input => "Oh yeah yeah"

Output =>

O
Oh
Oh
Oh y
Oh ye
Oh yea
Oh yeah
Oh yeah
Oh yeah y
Oh yeah ye
Oh yeah yea
Oh yeah yeah
Oh yeah yea
Oh yeah ye
Oh yeah y
Oh yeah
Oh yeah
Oh yea
Oh ye
Oh y
Oh
Oh
O

Note that there are apparent distortions in the above test case's output's shape (for instance, line two and line three of the output appear the same). Those are because we can't see the trailing whitespaces. Your program need NOT to try to fix these distortions.

Winning Criterion
This is code-golf, so the shortest code in bytes in each language wins!

I am planning to make some more YouTube comments related challenges in the future; hence the YouTube Comments #1 in the title.

Is returning a array of lines allowed?

@someone Yes, it is allowed, in accordance with standard I/O defaults

Can we take input as an array of characters and return an array of arrays of characters?

Closely related

Can the input be ""? What about a single character like "H"? If so, what should be the output for both of those cases?

@AdmBorkBork No, the input cannot be "". As for "H", the desired output is H only. I am sincerely sorry for such a late reply.

@Shaggy If the community rules allow it, then sure.

Are leading and trailing blank lines permitted?  (i.e. output is 2*s.length + 1 lines, but the first and last lines are empty)

Can we assume the input only contains chars in the ASCII 32--127 range? In particular, can we assume it doesn't contain char(0)?

@Chronocidal Yes, leading and trailing blank lines are permitted.

@LuisMendo Yes, you can assume that the input will only contain printable ASCII characters. I'll edit accordingly.

brainfuck, 32 bytes
,[[<]>[.>]++++++++++.,[>>]<[-]<]

Try it online!
The same loop is used for both halves of the pattern.
Explanation:
,             Take first input character as initial line
[             Until line to output is empty:
  [<]>        Move to beginning of line
  [.>]        Output all characters in line
  ++++++++++. Output newline
  ,           Input next character
  [>>]        Move two cells right if input character nonzero
  <[-]        Otherwise remove last character in line
  <           Move to new last character in line
]

That's just plain awesome. I was trying to do something in brainfuck but it came out about 10 times this long and still didn't work properly.

Never thought I'd see a challenge where the brainfuck answer was actually scoring competitively, awesome work!

JavaScript (ES6), 36 bytes
f=([c,...r],s=`
`)=>c?s+f(r,s+c)+s:s

Try it online!
Commented
f = (             // f is a recursive function taking:
                  //   the input string split into:
  [c,             //     c   = next character (may be undefined if we've reached the end)
      ...r],      //     r[] = array of remaining characters
  s = `\n`        //   the output string s, initialized to a linefeed
) =>              //
  c ?             // if c is defined:
    s +           //   append s (top of the ASCII art)
    f(r, s + c) + //   append the result of a recursive call to f, using r[] and s + c
    s             //   append s again (bottom of the ASCII art)
  :               // else:
    s             //   append s just once (this is the final middle row) and stop recursion

very nice answer :D

different OSes different sizes got to hate line endings so windows reports as 37 bytes because of \r\n over Unix \n :D

@MartinBarker On Windows, I'm using Notepad++ with the default Line Ending turned to Unix (LF). Problem solved once and for all. :)

Longer than the BF solution...that's a first

05AB1E (legacy),  4  3 bytes
Crossed out  4  is no longer 4 :)
η.∊

Try it online or verify all test cases.
Explanation:
η     # Get the prefixes of the (implicit) input-string
 .∊   # Vertically mirror everything with the last line overlapping
      # (which implicitly joins by newlines in the legacy version of 05AB1E)
      # (and output the result implicitly)

In the new version of 05AB1E, and explicit » is required after the η, which is why I use the legacy version of 05AB1E here to save a byte.

3 bytes alternative provided by @Grimy:
ηû»

This version works in both the legacy and new version of 05AB1E.
Try it online (legacy), try it online (new version) or verify all test cases (new version).
Explanation:
η     # Get all prefixed of the (implicit) input-string
 û    # Palindromize each string in this list
  »   # And then join the list of strings by newlines
      # (after which the result is output implicitly)

Hmm, this seems to 6 bytes in UTF8: \xce\xb7\x2e\xe2\x88\x8a

@rubenvb In UTF-8 it's indeed more. 05AB1E uses, just like some some of the programming languages used in other answers (i.e. Jelly; Japt; Charcoal) it's own source code (which is CP-1252 in the case of 05AB1E), where each of the 256 characters it knows is a single byte.

All right, fair enough :).

@KevinCruijssen PHP seems to think that these characters are invalid for CP-1252, but could just be a PHP bug: https://3v4l.org/UC1QE

@rubenvb i'm still not convinced that CP-1252 is the answer here, see above.. =/ (PS: php-strings are byte arrays, the string length of a php string is always the number of bytes.)

@hanshenrik Tbh, I'm not 100% sure if it's CP-1252. All I know is that the linked code-page (the first link in my first comment, or the link in the bytes of the answer-title; so this one) is the code page 05AB1E uses. I've heard somewhere it's CP-1252, but maybe I'm mistaken in that and it's a custom codepage instead. I do know that those 256 characters are 1 byte each for 05AB1E programs.

@KevinCruijssen hmm, can you take a screenshot of your source code file opened in a hex editor? (if you don't have a hex editor nearby, HxD is a great hex editor for windows systems, and Bless is a decent hex editor for Linux ) - or can you upload your source code file on some file sharing website like http://mega.co.nz ?

come to think of it, if you're on linux, you can probably just do cat source.file | base64 | pastebinit

@hanshenrik Good question. It is indeed not CP-1252, but in fact the 05AB1E encoding, which is the custom encoding it uses. The bytes of this code in hex are 08 2e 17, which you can run and verify with the --osabie flag: https://tio.run/##S0oszvifnJ@SaqsUU2FgEVNhlBpTYWiu9D81OSNfQTdPQTdVQQUkr2CnUJJaXKKXmJTKVVBZkpGfZ6ygn19Qom9gmphkmKqfX5yYlJmqV1CpoKsLYcPV//@fmJSckgoA

@Adnan well that satisfies my curiosity, thanks guys!

ηû» for modern 05AB1E.

@Grimmy Ah, nice one. That one works in both 05AB1E versions. I've added it to the answer.

x86-16 machine code, IBM PC DOS,  44  43 39 bytes
00000000: d1ee ad8b d648 93b7 248a cbd0 e13a d975  .....H..$....:.|
00000010: 01fd ac86 3cb4 09cd 2186 3cb8 0d0e cd10  ....<...!.<.....
00000020: b00a cd10 e2e7 c3                        .......

Build and test YT.COM using xxd -r from above.
Unassembled:
D1 EE       SHR  SI, 1              ; point SI to DOS PSP at 80H (SI intialized at 100H)
AD          LODSW                   ; load input length into AL, SI = 82H
8B D6       MOV  DX, SI             ; save start of string pointer
48          DEC  AX                 ; remove leading space from string length
93          XCHG AX, BX             ; save string length in BL
B7 24       MOV  BH, '$'            ; put end-of-string marker in BH
8A CB       MOV  CL, BL             ; set up loop counter in CL
D0 E1       SHL  CL, 1              ; number of lines = 2 * string length - 1
    LINE_LOOP:
3A D9       CMP  BL, CL             ; does CL = string length?
75 01       JNZ  LINE_OUT           ; if not, go to output line
FD          STD                     ; otherwise flip DF to descend
    LINE_OUT:
AC          LODSB                   ; increment or decrement SI
86 3C       XCHG BH, [SI]           ; swap current string byte with end of string delimiter
B4 09       MOV  AH, 9              ; DOS API display string function
CD 21       INT  21H                ; write substring to console
86 3C       XCHG BH, [SI]           ; restore string byte
B8 0E0D     MOV  AX, 0E0DH          ; AH = 0EH (BIOS tty function), AL = CR char
CD 10       INT  10H                ; write CR to console
B0 0A       MOV  AL, 0AH            ; AL = LF char
CD 10       INT  10H                ; write LF to console
E2 E6       LOOP LINE_LOOP          ; move to next line
C3          RET                     ; return to DOS

Explanation
Loop 2 * input length - 1 for each row.  The DOS API's string display function (INT 21H,9) writes a $-terminated string to the screen, so each time through the loop the character after the last to be displayed is swapped with the end-of-string terminator.
The loop counter is compared with the string length, and if it's greater (meaning the ascending part of the output) the string/swap position is incremented, otherwise it's decremented.
Standalone PC DOS executable program, takes input string from command line.
Output

-1 byte use SHR SI, 1 instead of MOV - thanks to gastropner!
-1 byte flipping loop comparison
-1 byte write newline directly instead of as string
-1 byte use XCHG instead of MOV
-1 byte use STD / LODSB to ascend/descend SI pointer

Most DOS flavours have SI = 100h upon loading a COM file. This can save you a byte by replacing the first instruction with SHR SI, 1.

@gastropner very clever! Turns out the original won't run on DOS 1.0 anyway since it counts on CH being 0 (would cost +2 bytes to initialize, which isn't worth it just for DOS 1).  Updated with new version!

Do you have to enter the date everytime you open the terminal?

@user14492 ha, no! I just forgot to crop that part out of the DOS screenshot!

Is this assembler ? It's the first time I see this since my student time. (= long, long ago)

Outgolfed

MATL, 8 bytes
nZv"G@:)

Try it online!
Please like this post for the smiley :) in the code it took me a lot of time to make.
n  % Length of the input string
Zv % Symmetric range ([1 2 ... n ... 1])
"  % For each k in above range
G  % Push input
@: % Push [1 2 ... k]
)  % Index

Python 2, 60 52 bytes
f=lambda s,n=1:s[n:]and[s[:n]]+f(s,n+1)+[s[:n]]or[s]

Try it online!
Python 3.8 (pre-release), 50 bytes
f=lambda s,n=1:s>(x:=s[:n])and[x,*f(s,n+1),x]or[s]

Try it online!

Does this depend on a forthcoming feature of 3.8? Which feature?

@alexis This is using an assignment expression: x:=s[:n].

Ah, I see it now thanks :-) I've read about the feature before, looking forward to it. Still miss it from my C days...

These don't print the output though. They just make the array, right?

@JadenTravnik Python automatically dupms the last expression result if running interactively through a console

@JadenTravnik It's a lambda expression (an anonymous function), and functions are allowed by default.

J, 11 bytes
Anonymous tacit prefix function. Returns a space-padded character matrix.
[:(}:,|.)]\

Try it online!
]\ the list of prefixes
[:(…) apply the following function to that list
 |. the reverse list
 , prepended with
 }: the curtailed (without last item) list

[:( and }:,| look so sad…

But it's (}: which is a happy person with a fancy mustache

Perl 6, 31 bytes
{[\~](@_)[0...@_-1...0]}o*.comb

Try it online!
Anonymous code block that takes a string and returns a list of lines.
Explanation:
{                      }o*.comb   # Pass the list of characters into the codeblock
 [\~](@_)                 # Triangular reduce by concatenation
                          # e.g. The list [1,2,3,4] turns into [1,12,123,1234]
         [0...@_-1        # Return the elements from 0 to length of string minus 1
                  ...0]   # And back down to 0

It's funny that these days even golfed Perl is among the most readable contestants.

@ceasedtoturncounterclockwis Well, this is Perl 6. The Perl 5 answer is still unreadable

Japt -R, 4 bytes
å+ ê

Cumulative reduce on a string.
-1 byte thanks to @Shaggy
Try it online!

Sceptic about the "-R" that has to be included in the string (without it the output doesnt work)

@FlyingThunder Be a skeptic no more :) see here

@Quintec, I've taken to linking the flags in my solution headers to that meta post to try to preempt these sorts of comments.

Pretty sure convention is  + -flag or  -flag. Also, :| I forgot cumulative reduce was a thing, I swear I skipped over it every time I saw it

@ASCII-only Same, I only remembered it because I was thinking how I would solve this in APL and said "I wonder if Japt has this builtin". Also, didn't I use  -flag?

@Quintec but you linked to a meta post, not enclosed it in a codeblock (actually, you can even do both)

Japt -R, 9 7 bytes
-2 bytes thanks to Shaggy
Êõ@¯XÃê

Try it online!

7 bytes

@Shaggy oh wait... Ã is a thing

Another 300 rep on its way as soon as this question is eligible for a bounty.

5 bytes? (different approach)

@Quintec, cumulative reduce works on strings, too, so you don't need to split at the start. I'd also say that's different enough to warrant posting it yourself.

@Shaggy Ok, will do.

Perl 5 (-p), 26 bytes
s,.,$\=$`.$/.$\;"$`$&
",ge

TIO

Haskell, 52 50 44 bytes
f x=unlines$init<>reverse$scanr(\_->init)x x

-2 bytes by a variant of Ørjan Johansen's trick
-6 bytes by taking advantage of instance Semigroup b => Semigroup (a -> b)

Try it online!

Welcome to the site.  inits requires an import to be used so you are going to need to add import Data.List or something similar.

@SriotchilismO'Zaic Wasn't sure if that was necessary to count or not. Added, thanks!

Also I should mention we have a chat room for talking Haskell golfing.  If you have any thoughts or questions that's a great place.

I can't believe you came up with exactly what I was going to post:
putStr.unlines.((++)<*>reverse.init).tail.inits```

R, 79 65 62 58 bytes
write(substring(s<-scan(,""),1,c(1:(r=nchar(s)),r-1:r)),1)

Try it online!
-14 by Giuseppe's superior function knowledge
-3 with cleaner indexing
-4 thanks to Nick Kennedy and Giuseppe's move to scan and write
Avoiding loops (and substr) is nice.

loops are thoroughly unnecessary, as is sapply -- substring will do what you want (with an additional trailing empty line), and for 65 bytes! I definitely wouldn't have thought of substring if I hadn't seen your nice use of substr here.

Haha, good catch! I think I've learned more about alternate functions for the same job from your edits than anywhere else at this point.

Haha, R has a stupid amount of synonyms with subtle differences. Every time I feel like I know the best tool for the job, I find something else that's slightly better in a weird edge case...

How about Try it online! using scan and write? Only 59 bytes!

@NickKennedy 58 bytes if you replace "" with 1.

@Giuseppe thanks, didn’t know that. It also seems that using 2 outputs to stderr.

@NickKennedy that's neat, I couldn't find a way to use scan that didn't add more bytes. Will have to look into how write works, never really used it before.

Python 3.8 (pre-release), 48 bytes
lambda s,r='':(l:=[r:=r+c for c in s])+l[-2::-1]

Try it online!
Uses assignment expressions with := to accumulate a list of prefixes and then again to save the result to concatenate its reverse (without the first char).
Python 2, 51 bytes
f=lambda s,l=[]:s and f(s[:-1],[s]+l)or l+l[-2::-1]

Try it online!
We almost have the following nice 45-byte solution, but it has the original string twice and I don't see a short way to fix this.
f=lambda s,l=[]:s and f(s[:-1],[s]+l+[s])or l

Try it online!

Wouldn't you need to add some newline and print to get the desired output?

Something like print('\n'.join(f(s)))  ?

@JadenTravnik The community defaults (which this challenge follows) allow for functions in addition to programs. And the challenge author said in the comments that they are OK with a list of strings within joining as allowed by default, though I myself don't like this as a default and have downvoted it. See also the Python rules summary.

Huh. Ok, thanks for pointing that out. Im new ¯_(ツ)_/¯.
If thats the case, here is a competing 45-byte solution: x=[s[:i+1]for i in range(len(s))];x+x[-2::-1]

@JadenTravnik No problem, the rules are unfortunately scattered over the place. Your example though is a snippet which are not allowed. It needs to do input and output like s=input();x=[s[:i+1]for i in range(len(s))];print x+x[-2::-1]. See the examples at the top here.

Ah, ok. Thanks for pointing that out. :)

Jelly, 5 4 bytes
-1 byte thanks to @JonathanAllan!
¹ƤŒḄ

Try it online! I think this is my second Jelly answer? I don't know if this is optimal. I am more convinced of it being optimal. Returns an array of lines.
Explanation
¹ƤŒḄ     input: "Hi!"
¹Ƥ       prefixes of the input: [["H"], ["H", "i"], ["H", "i", "!"]]
  ŒḄ     bounce, using each array: [["H"], ["H", "i"], ["H", "i", "!"], ["H", "i"], ["H"]]

Another approach, proposed by @JonathanAllan, is ;\ŒḄ, which cumulatively reduces (\) concatenation (;), which is another way to generate prefixes.

We are allowed to yield an array of lines, so you can bump Y out of the code (I'd make the footer either ÇY or ÇŒṘ to avoid a full-program's implicit smashing print). On a side-note this is also equivalently implemented as ;\ŒḄ for the same byte-count (also you can pass the argument as"blah" as Jelly interprets this as a list of characters - yours is actually a list of lists of characters, as you'll see if you make the footer ÇŒṘ)

@JonathanAllan thanks! very interesting :)

C# (Visual C# Interactive Compiler), 123 109 94 84 74 bytes
Assumes we can return a char array array (I believe we can, as a char array is a valid representation for a string and a string array is a valid representation for multiple lines)

a=>new int[a.Length*2-1].Select((b,i)=>a.SkipLast(Math.Abs(a.Length-i-1)))

Try it online!

Charcoal, 5 bytes
Ｇ^Ｌθθ

Try it online! Link is to verbose version of code. Explanation: Ｇ draws a filled polygon, ^ specifies that the sides are down right and down left (the polygon then automatically closes itself), Ｌθ specifies the length of those sides as being the length of the original input and the final θ specifies the fill string.

Attache, 15 bytes
Bounce@Prefixes

Try it online!
Pretty simple. Bounces (appends reverse without center) the Prefixes of the input.
Alternatively, 21 bytes: Bounce@{_[0..0:~-#_]}, re-implementing prefix.

Brachylog (v2), 6 bytes
a₀ᶠ⊆.↔

Try it online!
Function submission, returning an array of lines. Loosely based on @Fatalize's answer.
Explanation
a₀ᶠ⊆.↔
    .↔  Find a palindrome
   ⊆      that contains, in order,
  ᶠ       all
a₀        prefixes of {the input}

Tiebreak order here is set by the ⊆, which, when used with this flow pattern, prefers the shortest possible output, tiebroken by placing the given elements as early as possible. The shortest possible output is what we want here (due to it not being possible to have any duplicate prefixes), and placing the given elements (i.e. the prefixes) as early as possible will place them in the first half (rounded up) of the output. Given that we're also requiring them to be placed in the same order, we happen to get exactly the pattern we need even though the description we gave Brachylog is very general; the tiebreaks happen to work out exactly right, causing Brachylog to pick the output we want rather than some other output that obeys the description.

APL (Dyalog Unicode), 9 bytesSBCS
Anonymous tacit prefix function. Returns list of strings.
(⊢,1↓⌽),\

Try it online!
,\ the list of prefixes (lit, the cumulative concatenation)
(…) apply the following function to that list:
 ⌽ the reversed list
 1↓ drop the first item
 , prepend
 ⊢ the unmodified list

sed, 31 35 bytes
:x
h
s/.\n.*\|.$//
/^$/{x;q}
H
G
bx

Try it online!
Explanation
At the beginning of each iteration of the loop, pattern space is some "central chunk" of the desired output, and each loop adds a shortened copy to the top and bottom.
:x
h                  Copy the current chunk to hold space
s/.\n.*\|.$//      Remove the last letter of the first line, and all other lines (if there are any)
/^$/{x;q}          If pattern space is empty we're done; output hold space
H                  Add the shortened line to the end of hold space
G                  and add the new hold space to pattern space.
bx

Nice one, but the the middle line (the full original input) seems to be output 3 times. At least with GNU sed. Same on TIO. Which sed implementation you use and how you pass it the input? (BTW, changing the substitution to s/.\n.*\|.$// fixes it.)

Ah, you're right. It's not a problem with my sed implementation (using GNU version 4.2.1) , I just didn't notice the bug. I've played around with some other fixes and can't find anything that adds fewer than four bytes so I'm adopting your fix, thank you.

PowerShell, 46 bytes
($l=$args|% t*y|%{($s+=$_);++$i})+$l[$i..0]|gu

Try it online!

PowerShell, 42 bytes (YouTube special, dirty)
It is known that the maximum length of a comment on youtube is 10,000 characters. Ok, use this as the upper limit.
($l=$args|% t*y|%{($s+=$_)})+$l[1e4..0]|gu

Try it online!

x86-16 machine code, IBM PC-DOS, 33 bytes
Hexdump:
00000000: bf 82 00 91 89 fa e8 0a 00 74 06 41 eb f8 e8 02  .........t.A....
00000010: 00 e2 fb b4 40 cd 21 b0 0d ae cd 29 b0 0a cd 29  ....@.!....)...)
00000020: c3                                               .

Commented assembly:
        [org 0x100]
start:
        ; DI <- first command line argument
        mov     di, 0x0082
        ; DOS startup state abuse 1: set CX to zero by swapping AX (0x0000)
        xchg    cx, ax
        ; DX <- DI
        mov     dx, di
.loop1:
        ; A multitasking loop.
        ; This both prints the string up to the full length and counts
        ; the chars by scanning for '\r'.

        ; Print DS:DX(CX)
        ; We test for the end of string when printing
        ; the newline by using SCASB.
        call    putsn
        ; If the SCASB returned true, break to the end of .loop2
        ; We don't go to the top because it would print the full
        ; length string twice.
        jz      .next
        ; Increment the length and character counter
        inc     cx
        ; Loop to loop1
        jmp     .loop1

.loop2: ; Shortening loop
        ; Print
        call    putsn
.next:
        ; while (--CX)
        loop    .loop2
        ; Fallthrough: prints an empty line (as CX is 0) and exits

        ; Prints CX chars from DX, followed by a newline.
putsn:
        ; DOS startup state abuse 2: BX is 0x0000.
        ; DOS lets you write to STDIN and it still prints to the screen.
        ; Why? I have no idea. It's very convenient though. Note that
        ; this behavior is consistent on DOS 6.22 and FreeDOS 1.3rc4.
        ;
        ; write(0, argv, CX)
        mov     ah, 0x40
        int     0x21
        ; Print \r\n with INT 29h
        mov     al, 13
        ; Since we have \r in AL, we can use SCASB to check
        ; for the end of the string when we return.
        ; Interrupts save the flags.
        ;
        ; Yes, this reads out of bounds on the second loop,
        ; but it is DOS, who cares?
        scasb
        int     0x29
        mov     al, 10
        int     0x29
        ret

To be even with 640KB, I also used the command line arguments, but I made some changes:

I use write (21:40) instead of puts (21:09). While it does require manually printing a newline, it lets me manually control the length just by changing CX.
I count the length of the command line arguments on the fly.
I did some other tricks.

This abuses the newline rule: it actually prints empty strings at the start and end.

C (gcc), 68 67 64 59 bytes
thanks @ceilingcat for -6
thanks @gastropner for -5
i,j;f(char*s){for(j=1;i+=j;puts(""))j-=2*!s[write(1,s,i)];}

Try it online!

Does not appear to be reusable.

@gastropner what do you mean, not reusable?

@Baldrickk If you call the function again with a new string, it doesn't work.

@gastropner so?  Since when was that a requirement? It works fine running the program again with a new string.

@Baldrickk https://codegolf.meta.stackexchange.com/a/4940/758869

Umm... if you want to reusable version you can make it by adding j=0 3 bytes in the first for statement.

59 bytes

Ruby, 51 42 40 bytes
f=->s,i=1{s[i]?[t=s[0,i],*f[s,i+1],t]:s}

Try it online!
Thanks to Doorknob for -2 bytes.

You can save 2 bytes by replacing ... with ,

J, 12 bytes
]\,[:}.@|.]\

Try it online!
Still 1 byte longer than Adám's
K (oK), 12 11  bytes
-1 byte thanks to ngn
{x,1_|x}@,\

Try it online!

Did I outgolf the master‽

@Adám  I'm far from being a J master :) There are many J coders here better than I am.

-1 byte for oK: {x,1_|x}@,\

JavaScript (Node.js), 90 bytes
This can probably be golfed alot more, Arnauld already has a way shorter one but I had fun atleast!
s=>{a=[];for(c=s.length-1;c--;)a[c]=s.slice(0,c+1);return[...a,s,...a.reverse()].join`\n`}

Try it online!

SNOBOL4 (CSNOBOL4), 118 bytes
	N =INPUT
	L =1
1	X =LT(X,SIZE(N)) X + 1	:F(D)
O	N ARB . OUTPUT POS(X)	:($L)
D	X =GT(X) X - 1	:F(END)
	L ='D'	:(O)
END

Try it online!
There appears to be a bug in this implementation of SNOBOL; attempting to replace the label D with the label 2 causes an error, although the manual for Vanilla SNOBOL indicates that (emphasis added)

If a label is present, it must begin with the first character of the line. Labels provide a name for the statement, and serve as the target for transfer of control from the GOTO field of any statement. Labels must begin with a letter or digit, optionally followed by an arbitrary string of characters. The label field is terminated by the character blank, tab, or semicolon. If the first character of a line is blank or tab, the label field is absent.

My supposition is that the CSNOBOL interpreter only supports a single label that begins with an integer.

PHP, 79 bytes
function y($s,$l=1){echo$t=substr($s,0,$l)."
",$l<strlen($s)?y($s,$l+1).$t:'';}

Try it online!
Recursive in PHP as a function.  Ungolfed version:
function y( $s, $l=1 ) {
    echo $t = substr( $s, 0, $l ) . "\n";
    if ( $l < strlen( $s ) ) {
        y( $s, $l+1 );
        echo $t;
    }
}

Call as y('String') outputs:
S
St
Str
Stri
Strin
String
Strin
Stri
Str
St
S

Or 69 bytes iterative with php -nF input as STDIN (basically a port of several other answers).
while(++$x<2*$l=strlen($s=$argn))echo substr($s,0,$l-abs($x-$l)),"
";

Try it online!

APL+WIN, 31 bytes
Prompts for input of string:
 ⊃((⍳n),1↓⌽⍳n)↑¨(¯1+2×n←⍴s)⍴⊂s←⎕

Explanation:
(¯1+2×n←⍴s)⍴⊂s create a nested vector of the string of length =1+2x length of string

((⍳n),1↓⌽⍳n)↑¨ progressively select elements from each element of the nested vector
              following the pattern 1  2 ...to n to n-1 ... 1

⊃ convert nested vector into a 2d array.

F# (.NET Core), 67 61 bytes
let l=s.Length
[1..l*2-1]|>Seq.map(fun i->s.[..l-abs(i-l)-1])

Try it online!
Input is a string and output is a seq<string>
Another solution could be let f(s:string)=for i=1 to s.Length*2-1 do printfn"%s"s.[..s.Length-abs(i-s.Length)-1] for 80ish bytes... I am not sure that it is worth looking into.

Haskell, 36 bytes
foldr(\h l->(h:)<$>[]:l++min[[]]l)[]

Try it online!
Outputs a list of lines.
Haskell, 37 bytes
f[c]=[[c]]
f(h:t)=(h:)<$>"":f t++[""]

Try it online!

C (gcc), 62 60 58 bytes
-2 bytes by using the write() approach of jaeyong-sung's answer.
i,d;f(char*s){for(d=1;write(1,s,i+=d-=!s[i]*2);puts(""));}

Try it online!

[Assembly (nasm, x64, Linux)], 35 32 bytes
This is a function that takes a string (Pointer in RSI) and it's length (number in ebp), and outputs the required string to STDOUT.
EDI and EDX MUST be 0

ytc:
	;Actual setup
	inc ebp
	inc edi ;FD for STDOUT
	push rdi ;Value to add/subtract
	mov bl, 0Ah
.lp:
	add edx, [rsp] ;Str Length +- 1
	jz .end
	cmp edx, ebp
	jne .clp
	push -1
.clp:
	xchg [rsi+rdx-1], bl
	mov al, 1
	syscall
	xchg [rsi+rdx-1], bl
	jmp .lp
.end:
	ret

Try it online!

BASH (+ GNU coreutils) 72 bytes
Takes input string from STDIN (one line)
read s;for i in `seq ${#s};seq $((${#s}-1)) -1 1`;do echo ${s:0:$i};done

example:
echo "Oh yeah yeah" | ./script.sh

output:
O
Oh
Oh
Oh y
Oh ye
Oh yea
Oh yeah
Oh yeah
Oh yeah y
Oh yeah ye
Oh yeah yea
Oh yeah yeah
Oh yeah yea
Oh yeah ye
Oh yeah y
Oh yeah
Oh yeah
Oh yea
Oh ye
Oh y
Oh
Oh
O

Explanation:
# read string from STDIN into variable $s
read s

# `seq ${#s}` : sequence of numbers from 1 to length of string followed by
# `seq $((${#s}-1)) -1 1` : sequence of numbers from length-1 downto 1

# loop through sequence
for i in `seq ${#s};seq $((${#s}-1)) -1 1`;do

    # print substring of $s from position 0 to i
    echo ${s:0:$i}

# end of loop
done

You can squish it down to 67 bytes... read s;for i in \seq ${#s};seq $[${#s}-1] -1 1`;{ echo ${s:0:$i};}` using some bash golf tricks. Example: https://ideone.com/Pw94LT

I golfed it down to 65 in bash using weird iterators! Here's my solution... tio.run

Julia, 40 bytes
s->(a=cumprod([s...]);[a;a[end-1:-1:1]])

Try it online!
Gets the first half by taking the cumulative product (* is string concatenation in Julia) of the array of characters, then adds this array to itself reversed minus the first element.
Thanks to @Kirill L. for 4 bytes.

In modern Julia, cumprod and reverse accept string inputs, bringing the solution to 32 bytes.

Octave, 58 bytes
for k=1:(n=nnz(s=input(''))*2)-1
disp(s(1:min(k,n-k)))
end

Try it online!

I came up with essentially the same answer in MATLAB before I saw yours, but you get to take shortcuts in Octave with those compound assignments saving several bytes... I did briefly consider if any char maps to zero, such that nnz would miss it?

@Wolfie Somehow I assumed the input would not contain char(0), but you are right, it might be the case. I've asked for the OP if we can assume the standard ASCII range 32--127

@Wolfie Confirmed: only printable ASCII

Brachylog, 8 bytes
a₀ᶠ;Lc.↔

Try it online!
Explanation
a₀ᶠ          Find all prefixes of the input
   ;Lc.      The output is that list of prefixes with something unknown appended at the end
      .↔     The output reversed is itself (i.e. it's a palindrome)

MBASIC, 103 bytes
1 INPUT S$:N=1
2 PRINT LEFT$(S$,N):IF N<LEN(S$) THEN N=N+1:GOTO 2
3 N=N-1:PRINT LEFT$(S$,N):IF N>1 THEN 3

C# (Visual C# Interactive Compiler), 82 81 bytes
x=>{for(int l=x.Length,i=0;i<l*2-1;)WriteLine(x.Substring(0,l-Math.Abs(++i-l)));}

Try it online!
String as input and output to std

Pyke, 6 bytes
BE 27 4F 5F 2B 58

Try it here!
        - input() (implicit)
.>      - prefixes(^) (1 byte)
  'O_   - ^[:-1], reversed(^)
     +  - [^]
      X - "\n".join(reversed(^))

MathGolf, 7 bytes
£rñ{l<n

Try it online!
Explanation
£         length of array/string with pop
 r        range(0, n)
  ñ       pop(a), push palindromize(a) string/list/number
   {      start block or arbitrary length
    l     read string from input
     <    slice input string at index
      n   newline char

><>,  44  41 bytes
i:0(?^l&}21.>ao&~
:o}1&:1-&) ?^
l&21.>~{~

Try it online!

VBA, 54 51 Bytes
(-3 bytes now that leading & trailing 0-character lines are confirmed as permitted)
x=Len([A1]):For i=-x To x:?Left([A1],x-abs(i)):Next

Just a simple loop from -Length to Length, omitting that many Absolute characters from the end each time
Input is cell A1 of the ActiveSheet.  Output and Code are in the Immediate window

Kotlin, 62 bytes
{s->s.indices.map{s.take(it+1)}.let{it+it.reversed().drop(1)}}

Could probably be golfed more, but this is what I came up with.
Try it online!

C, 78 bytes

#define f;printf("%.*s\n",i,d));
i;y(char*d){for(;i++<strlen(d)f for(i--;i--f}

73

Husk, 6 bytes
S+o↔hḣ

Try it online!
Takes input as an argument.
S      Apply the first argument to the third argument and to the second argument applied to the third argument:
 +     concatenation,
 o     the composition of
  ↔    reversal
  h    with removal of the last element,
 ḣ     every prefix of
       the input.

...I may need to not try to explain combinators in plain English.

I feel like there might be a way to shave a byte off this on account of this having used both S and o, but I'm not sure...

Pyth, 10 bytes
j+._zt_._z

Try it online!
j          # Join the final array with newlines and print
 +         # Join the two resulting arrays:
  ._z      #   1. All prefixes of the input (z)
     t     #   2. Remove the first element (full word)
      _    #      of the reverse
       ._z #      of all prefixes of the input (z)

Thanks to ASCII-only for helping get the bytes down!

16

yours can also be 16

10

@ASCII-only The 16 ones have a trailing empty line, I didn't realize that was allowed so I had had added the Ik to fix that. That 10-byte entry is seriously impressive, why not submit it as a seperate answer?

i don't mind if you post it, 2. don't have time today, 3. it's 90% done by a builtin lol, i don't even know Pyth well

Python 3, 79 72 bytes
Thanks Jo King for helping me save 7 bytes
I'm a bit late to this golf, but I was bored and didn't see a Python 3 one that gave a printable string and not a list. This isn't exactly very short but this is my first code golf post :)
lambda x:'\n'.join(x[:[i,len(x)-i][i>len(x)]]for i in range(1,len(x)*2))

Try it online!

Welcome to CGCC! Anonymous lambdas are acceptable submissions, so you can remove the f=. You can also change the if statement to a list selection ([i,len(x)-i][i>len(x)]) for a total of 72 bytes.

Scala, 41 bytes
s=>s.inits.toSeq.reverse++s.inits.drop(1)

Try it online!
Scala, 61 57 bytes
s=>1.to(2*s.size-1).map(x=>s.take(s.size-(s.size-x).abs))

Try it online!

-4 thanks to user!

You can use .abs directly on Int to get 57 bytes.

The 41 byte version is really cool, by the way. Wish I could upvote again.

Thanks user :) I found it while searching something else. It was pure luck

Canvas, 3 bytes
［］─

Try it here!

Branch, 32 bytes
,[[^]/[./]10.,]^[0^[^]/[./]10.^]

Try it on the online Branch interpreter!
Explanation
,                 Read a character from STDIN
[            ]    While true (while input is not EOF)
 [^]              Keep going up until we hit 0; this is the parent of the first input node
    /             Go to the input node
     [./]         While true, output the node and descend; outputs all input at this point
         10.      Output 10 (newline)
            ,     Read the next character
^                 Go up one space (this puts us on the last input node)
[              ]  While true (while we haven't deleted all of the input yet)
 0^               Zero the current value and go up (delete the last character)
   [^]/           Go to the top again
       [./]       Output all of the input again (gradually gets deleted)
           10.    Output newline
              ^   Go up again; this is the new last input character

This can actually be ported quite easily.
brainf***, 56 bytes
,[[<]>[.>][-]++++++++++.,]<[[-]<[<]>[.>][-]++++++++++.<]

Try it online!
Basically does the same thing as above. However, BF can't set the value of a cell like Branch can, so instead we can zero with [-] (which doesn't actually work well in Branch because long long int can take a long long time to zero if its initial value is -1) and then to get 10, we can just do + 10 times after zeroing.

Vyxal j, 3 bytes
¦øm

Try it Online!
-3 thanks to lyxal
¦   # Prefixes
 øm # Palindromised
    # Joined by newlines

Knight, 41 bytes
;=aP;=nF;W<=n+1nLaO GaFn;OaW=aSa-LaT1""Oa

Nothing too fancy, we just print out the first half, then the middle, then the second.
; = a PROMPT # read stdin
; = n FALSE # will coerce to `0` within the `WHILE` condition, but saves us a space from `=n 0`

# until we're at the length of `a`, print the prefix [0..n] from `a`
; WHILE < (=n + 1 n) (LENGTH a)
    OUTPUT (GET a FALSE n)

# output the entire thing
; OUTPUT a

# continue removing pieces from the end of `a` until it's empty, and printing `a` in the process
WHILE (= a SUBS a (- LENGTH a TRUE) 1 "")
    OUPUT a

You should use GaF-LaT.

Vyxal j, 2 bytes
¦∞

Try it Online!

R, 86 bytes
x=utf8ToInt(scan(,''))
for(i in c(y<-1:sum(x|1),rev(y)[-1]))cat(intToUtf8(x[1:i]),"
")

Try it online!
I'm learning more and more about better ways to manipulate strings in R, so I'm somewhat proud of this answer. The only part I don't like is the for loop portion, which I feel could definitely be golfed.

what about y<-seq(x)?

@Droplet you have to be quite careful about seq(x)! seq(x) behaves like seq_along(x) so long as x is not an integer or double of length 1. In that case, if x=c(65), for example, then seq(x) instead returns 1:x, which would not be the right behavior here. It's rather frustrating!

You're right, I didn't think of the case when s was just one letter

is the purpose of x=utf8ToInt(scan(,''))?

neat y<-seq(a=x) trick that somebody introduced (I forget who) try it online for -2 bytes!

Factor, 77 bytes
: f ( s -- ) dup length [1,b] dup reverse 1 tail append [ head ] with map . ;

Try it online!

Wolfram Language (Mathematica), 100 bytes
StringJoin[#~Join~Reverse[#][[2;;]]&[Append[Take[#,i],"\n"]~Table~{i,1,Length[#]}&[Characters[#]]]]&

Try it online!

Nim, 83 76 bytes
let s=readline(stdin)
let l=len(s)
for a in 1..l*2-1:echo(s[0..<l-abs(a-l)])

Try it online!
My first time golfing in Nim. All inputs are welcome!
This is a port of my F# and C# answer.

-7 bytes by using the [a..<b] instead of substr() (source)

Röda, 37 bytes
f s{{seq 1,#s-1;seq#s,1}|[s[:_],"
"]}

Try it online!
Explanation:
f s{ /* Function f(s) */
 {
  seq 1,#s-1; /* Push numbers 1..#s-1 to the stream (#s = length of s) */
  seq #s,1    /*   --..--     #s..1    --..-- */
 }|
 [       /* Print the following things for each _ in the stream: */
  s[:_], /*  Substring of s from 0 to _ */
  "
"        /*  Newline */
 ]
}

JavaScript (Node.js), 91 bytes
a=>{r=[];for(i=0;++i<a.length;)r.push(a.slice(0,i));return[...r,a,...r.reverse()].join`\n`}

Try it online!

C# (Visual C# Interactive Compiler), 76 bytes
x=>{for(int i=0,s=1;s+i>0;s=i<x.Length?s:-s)WriteLine(x.Substring(0,i+=s));}

Try it online!
Using an iterative approach, as opposed to LINQ.
I did not realize until after I posted, but my answer is pretty similar to aloisdg's answer. Although they are different enough, I might just leave mine too :)

Gald you posted it. I like it!

Python 2, 68 63 bytes
i=input()
j=[i[:x]for x in range(1,len(i))]
print j+[i]+j[::-1]

Try it online!
-5 thanks to @pppery for spotting an unneeded variable declaration.
Longer than the other Python answers but just another way of doing it.

63 bytes

@pppery Thanks for that and well spotted. Leftover from something I had tried earlier!

Java (JDK), 86 bytes
s->{for(int i=0,l=s.length();++i<2*l;)System.out.println(s.substring(0,i<l?i:2*l-i));}

Try it online!

Python 2, 122 90 bytes
A worse solution of @xnor's
u=lambda n,s,b:s[:b-abs(n-b)]+'\n'+u(n+1,s,b)if n<2*b else""
def c(w):print(u(0,w,len(w)))

Try it online!

APL(NARS), 24 char, 48 bytes
{⊃{w[⍵]}¨k,1↓⌽k←⍳¨⍳≢w←⍵}

test and how to use it:
  h←{⊃{w[⍵]}¨k,1↓⌽k←⍳¨⍳≢w←⍵}
        h ,'1'
1
  h '12'
1
12
1
  h '123'
1
12
123
12
1

comment: it would build one array of ranges [(1) (1 2) (1 2 3) ecc]
and the code pass each of them to the function {w[⍵]}

Use ⌷ and a train, and return a vector of vectors to save: {(⊂¨(+,1↓⌽)⍳¨⍳≢⍵)⌷¨⊂⍵} Try it online!

Wolfram Language (Mathematica), 63 bytes
(L=2StringLength@#;Do[Print@StringTake[#,Min[n,L-n]],{n,L-1}])&

Try it online!

Gaia, 3 bytes
…ṫṣ

Try it online!
As simple as it gets.
…	| prefixes
 ṫ	| palindromize
  ṣ	| join with newlines

Bytes? These look like Unicode characters to me.

@MarkJeronimus Gaia, like some other golfing languages, uses a custom code page so that each instruction is a single byte.

Zsh, 60 bytes
for c (${(s::Oa)1})(($#a))&&a=($c $c$^a $c)||a=$c
<<<${(F)a}

Try it online!
for c (${(s::Oa)1})          # (s::) splits the first parameter, (Oa) reverses order
    (( $#a )) &&             # if $a is not empty, then
        a=($c $c$^a $c) ||   # ...set a to the current character, then the array with
                             # the current character prepended to each element, else
        a=$c                 # ...set a to the current character
<<< ${(F)a}                  # print a; (F) joins on newlines

Python 2, 52 bytes
f=lambda s,i=1:s[i:]and[s[:i]]+f(s,i+1)+[s[:i]]or[s]

Try it online!
Returns a list of strings.

CJam, 28 29 bytes
l_,{_A)<oNo}fA_,{_A)~<oNo}fA;

My first CJam answer, so this can probably be golfed quite a lot
Edit: actually made it work correctly, at the cost of a byte
Try it online!

Wolfram Language (Mathematica), 59 bytes
Print/@Table[#~StringDrop~-Abs@i,{i,l=-StringLength@#,-l}]&

Try it online!

Taking input as a list of characters, and returning a list of character lists, 39 bytes:
Table[#~Drop~-Abs@i,{i,l=-Tr[1^#],-l}]&

Try it online!

Brain-Flak, 254 bytes
<>(<()>)<>{({}(<()>))<>{({}<>)<>}{}((()()()()()){})(<()>)<>{({}(<()>))(({}<>)<{({}<>)<>}>{})(<()>)<>{({}<>)<>}{}}{}}<>{({}<>)(<()>)<>{({}<>)<>}{}((()()()()()){})(<()>)<>{({}(<()>))(({}<>)<{({}<>)<>}>{})(<()>)<>{({}<>)<>}{}}{}<>}<>{{}}<>{}{}{({}<>)<>}<>{}

Try it online!
Harder than expected (or maybe i'm just not very talented in Brain-Flak ^^)
Explanation:
<>(<()>)<>              push 0 on second stack

                        ### copy words with increasing letter count to second stack
{                       while letters on stack
  ({}(<()>))            push 0 after first letter
  <>{                   move letters up to next 0 from second to first stack
    ({}<>)<>
  }
  {}                    pop 0
  ((()()()()()){})      append newline
  (<()>)                push new 0
  <>
                        ### append word from first to second stack
  {                     While letters on stack
    ({}(<()>))          push 0 after first letter
    (                   move letter on "third" stack for later use
      ({}<>)            move letter to other stack
      <{                move letters up to next 0 from second to first stack
        ({}<>)<>
      }>
      {}                pop 0
    )                   save letter from "third" stack
    (<()>)              push new 0
    <>{                 move letters up to next 0 from second to first stack
      ({}<>)<>
    }
    {}                  pop 0
  }
  {}                    pop 0
}
<>

                        ### copy words with decreasing letter count to second stack
{                       while letters on second stack
  ({}<>)(<()>)<>        move letter and 0 on first stack
  {                     move letters up to next 0 from second to first stack
    ({}<>)<>
  }
  {}                    pop 0
  ((()()()()()){})      append newline
  (<()>)                push new 0
  <>
                        ### append word from first to second stack
  {                     While letters on stack
    ({}(<()>))          push 0 after first letter
    (                   move letter on "third" stack for later use
      ({}<>)            move letter to other stack
      <{                move letters up to next 0 from second to first stack
        ({}<>)<>
      }>
      {}                pop 0
    )                   save letter from "third" stack
    (<()>)              push new 0
    <>{                 move letters up to next 0 from second to first stack
      ({}<>)<>
    }
    {}                  pop 0
  }
  {}                    pop 0
  <>
}

                        ### Tidy up
<>
{{}}                    delete input
<>
{}{}                    pop 0 and newline
{({}<>)<>}              move everything from second to first stack
<>
{}                      pop newline

Java (JDK), 107 106 bytes
(s)->{int l=s.length(),i=0;var r=new String[2*l-1];for(;i<l;r[i]=r[2*l-i-2]=s.substring(0,++i));return r;}

Loops over the characters of the input string and fills the resulting array from both sides.
Try it online!
107 -> 106: i=0 at initialisation so removed from for loop

Nice golf! +1'ed

Ly, 43 bytes
0>&ir[sp<l&:rp[o]r(10)o>]<rpr[p&s&o(10)o&l]

Try it online!
The logic here is to go through each character (codepoint in Ly) of the input string, add it to a second stack, print the accumulated characters, then go back to the input.  Once the input is exhausted, start with the "whole string" copy and do the reverse (remove a character, print, loop) until it's empty.
0>&ir[sp<l&:rp[o]r(10)o>]<rpr[p&s&o(10)o&l]  #
0                                            # Push 0 on the stack
 >                                           # Switch to stack on the right
  &i                                         # Read input onto the stack as codepoints
    r                                        # Reverse the stack
     [                  ]                    # Loop until stack is empty
      s                                      # Stash the current char
       p                                     # Delete it from the stack
        <                                    # Switch to stack on the left
         l                                   # Load the stashed character
          &:                                 # Duplicate stack on itself
            rp                               # Reverse stack, pop the top (0)
              [o]                            # Print stack until we hit a 0
                 r(10)o                      # Reverse the stack, print a LF
                       >                     # Switch to stack on the right
                         <                   # Time to shrink... Switch left
                          rpr                # Remove 0 at front of stack
                             [            ]  # While stack not empty
                              p              # Delete one character
                               &s            # Stash the whole stack
                                 &o          # Print the stack in order
                                   (10)o     # Print a LF
                                        &l   # Restore the stack

Python 3.8 (pre-release), 96 bytes
def f(s):
    for i in (a:=range(len(s))):print(s[:i+1])
    for i in a[::-1][1:]:print(s[:i+1])

Try it online!

Python 3, 65 63 bytes
Returns a list of lines.
lambda s:[s[:[i,2*len(s)-i][i>len(s)]]for i in range(len(s)*2)]

Try it online!

JavaScript (ES6), 64 bytes
Here's another JS solution:
s=>(l=s.length,f=i=>i<l*2?s.slice(0,i>l?l-i:i)+`
`+f(i+1):"")(1)

Red, 78 bytes
func[s][repeat n l: length? s[print copy/part s n]loop l[take/last s print s]]

Try it online!

Java 8, 92 91 bytes
s->{for(int i=0,l=s.length();i++<l*2-1;System.out.println(s.substring(0,i<l?i:l-(i-l))));};

Try it online!
-1 byte by using a for loop instead of a while

87 bytes

SAP ABAP (Unicode), 143 bytes
FORM i USING s.DATA(w) = 2 * strlen( s ).WHILE w > 0.w = w - 1.IF w < strlen( s ).WRITE:/ s(w).ELSE.WRITE:/ s(sy-index).ENDIF.ENDWHILE.ENDFORM.

Pretty straightforward subroutine. I'm using ABAP's substring access var+offset(length) and the system variable sy-index, which represents the index of the current loop. Other than that it's probably pretty self-explanatory, even though it's ABAP.

SAP ABAP (Non-Unicode), 141 bytes
FORM i USING s.DATA(w) = 2 * strlen( s ).WHILE w > 0.w = w - 1.IF w < strlen( s ).WRITE:/ s(w).ELSE.WRITE:/ s(sy(10)).ENDIF.ENDWHILE.ENDFORM.

Saving two bytes here by accessing the index component of sy like a substring, despite it being an integer value. In Unicode systems, characters are obviously multi-byte values, therefore using offsets is not allowed in mixed-type structures like sy. However, in a non-Unicode (ASCII-based) system, both digits of a number and characters are represented as one byte each, and offsets are allowed for structures like sy.
Conveniently index is the first 10-byte component of structure sy, so we don't need to use an offset. Otherwise we'd not be able to save anything here, as sy+x(10) is just as long as sy-index - or even longer if the offset was >= 10.

Output of both programs is obviously the same, screenshot below.

x86 machine code (Linux), 53 bytes
00000000: 89cf 31d2 4252 e814 0000 005a 803c 1100  ..1.BR.....Z.<..
00000010: 75f2 4a52 e806 0000 005a 09d2 75f4 c36a  u.JR.....Z..u..j
00000020: 015b 6a04 58cd 806a 0ab2 0189 e1b0 04cd  .[j.X..j........
00000030: 805e 89f9 c3                             .^...

Assembly:
section .text
	global func
func:				;Main function with args: char* ecx
					;Clear registers
	mov edi, ecx			;push pointer to original string
	xor edx, edx			;message length, start at 0
	loop_a:				;Increasing length loop:
		inc edx				;increment message length
		push edx			;save message length
		call print_text			;print string with newline
		pop edx				;get message length
		cmp byte [ecx + edx], 0		;If not at end of string:
		jne loop_a			;continue looping
	loop_b:				;Decreasing length loop:
		dec edx				;decrement message length
		push edx			;save message length
		call print_text			;print string with newline
		pop edx				;get message length
		or edx, edx			;If edx != 0:
		jne loop_b			;Continue loop
	ret

print_text:			;Function to print string (pointer in ecx) with newline:
	push 1
	pop ebx				;fd of stdout
	push 4
	pop eax				;syscall #4 (write)
	int 0x80			;run syscall (msg is in ecx)
	push 0xA			;push newline
	mov dl, 1			;set message length to 1
	mov ecx, esp			;set pointer for syscall to top of stack
	mov al, 4			;syscall #4 (write)
	int 0x80			;run syscall
	pop esi				;reset stack pointer
	mov ecx, edi			;get pointer to original string
	ret

Try it online!

Tip: try and merge the increasing and decreasing length loops, like i did in my x64 answer.

T-SQL query, 119 bytes
SELECT left(@,n)FROM(SELECT*,number/2+1n,len(@)k,number%2-.5m
FROM spt_values)x
WHERE type='P'and n+m<k
ORDER BY(n-k)*m

Try it online

PHP, 65 bytes
for(;($n=$argn)!=$s.=$n[$i++];$b="$s
$b")$a.="$s
";echo"$a$n
$b";

Try it online!
Tests: Try it online!
In a loop creates a word with one letter added to it towards input on each iteration until the word has one letter less than the input.
For example if the input is "Hello" the word in first iteration is "H" and on third iteration is "Hel" and on last iteration is "Hell".
This word is appended to $a and prepended to $b with a newline. At the end $a, input, a newline and $b are printed.

C (clang), 56 52 bytes
i;f(*s,l){for(i=0;write(1,s,++i<l?i:l--);puts(""));}

Try it online!
-4 thanks to @ceilingcat
Takes a string and its length as arguments.

GolfScript, 27 bytes
.1/{0=1$?1$<}%n*.-1%@n+n\+\

Try it online!

Fortran (GFortran), 79 bytes
character(99)a
read*,a
k=len_trim(a)
print('(a)'),(a(1:k-abs(i-k)),i=0,2*k)
end

Try it online!
Fortran. Always good for string manipulation

Keg, 37 bytes
?1&((⑻|⑩")(⑻|')⑹
,)⑺⑺((⑻|⑩")(⑻|')⑺
,)

Try it online!
I decided to try an interesting string shifting approach.

.+?, 28 bytes
((.+).(\n.+)*)
\2\n\1\n\2
$

Thanks to JoKing for giving the original regex, which I then golfed a bit.
Explanation
((.+).(\n.+)*)  The full pattern
(            )  Makes group 1 the entire match, used in the replacement
 (.+).          Makes group 2 every character on the first line, except for the last character
      (\n.+)*   Makes it match the rest, so it all will get replaced

\2\n\1\n\2      Replacement
\2              Group 2 (first line except last character)
  \n            Newline
    \1          Group 1 (entire match)
      \n        Newline
        \2      Group 2 (first line except last character)

$               This match always fails. Makes the first pair repeat until it doesn't match, which happens when the first line has less than 2 characters.

Try it online! (The second command line argument is input)

Factor + grouping.extras, 38 bytes
[ head-clump dup reverse rest append ]

Try it online!
            ! "Hello"
head-clump  ! { "H" "He" "Hel" "Hell" "Hello" }
dup         ! { "H" "He" "Hel" "Hell" "Hello" } { "H" "He" "Hel" "Hell" "Hello" }
reverse     ! { "H" "He" "Hel" "Hell" "Hello" } { "Hello" "Hell" "Hel" "He" "H" }
rest        ! { "H" "He" "Hel" "Hell" "Hello" } { "Hell" "Hel" "He" "H" }
append      ! { "H" "He" "Hel" "Hell" "Hello" "Hell" "Hel" "He" "H" }


text:
Swapless distances
Suppose you have a string \$s_0\$ and someone else has a hidden string \$s_1\$.  You don't know what \$s_1\$ is but they tell you that they can get from your string, \$s_0\$, to their string by making a certain number of moves \$d\$.  Each move can be one of the following:

Insertion : Add a character anywhere in the string
Deletion : Remove a character from anywhere in the string
Replacement : Replace one character with another anywhere in the string
Transposition : swap any two adjacent characters.

(this is Damerau-Levenshtein distance).
The question is how many moves do you need to get from \$s_0\$ to \$s_1\$ without using the transposition move (this is Levenshtein distance)?
Your task is to write a program or function that takes a string (list of positive integers is fine too) representing \$s_0\$ and a positive integer representing \$d\$ and output the minimal number of moves required to guarantee you can get to \$s_1\$ without transposition in the worst-case scenario.
This is code-golf your answer will be scored in bytes with fewer bytes being better.
Test cases
Using Strings
"Hello", 3 -> 4
"World", 2 -> 4
"aaaaa", 1 -> 1
"aaaaa", 2 -> 2
"abaaa", 3 -> 4
"Krypyp", 3 -> 5
"", 5 -> 5
"Hello", 0 -> 0

Using Integer lists
[1,2,3,3,4], 3 -> 5
[1,2,3,4,5], 2 -> 4
[1,1,1,1,1], 1 -> 1
[1,1,1,1,1], 2 -> 2
[1,2,1,1,1], 3 -> 4
[1,2,3,4,3,4], 3 -> 4
[], 5 -> 5
[1,2,3,3,4], 0 -> 0

It took a while to puzzle out, but I think this is asking for the largest Levenshtein distance among all strings with a given Damerau-Levenshtein distance from a given string.

@Nitrodon Yep that's another way to say it.

The Levenshtein distance from Hello to Hleol is 3, so the example test case would need to be something based on eHlol instead.  As for the length 6 test case, a distance of 5 is possible (e.g., rrKyypp)

Actually, Hello and eaHlol have Levenshtein distance 4: Hello → HeHlo → eHlo → eHlol → eaHlol

I couldn't find any string that shows "Hello", 3 -> 5. Are you sure it's 5? Otherwise my solution is wrong.

@japh I'm not really sure.  I am a little busy at the moment so I'll edit it down to 4.  I'll take a look at it later.

Suggest testcase "abbaab", 3 (should be 5, maybe)

Suggest testcase "Hello", 0, should be 0.

@tsh "abbaab", 3 results in 4

Haskell, 186 bytes
-- f :: [Int] -> Int -> Int
f s k|let a=pure<$>0:s;d#(x:z)|let w(y:z)|d>0=[y:x:z];w _=[]=[c++y++z|c<-[]:a,y<-[]:[[x]]]++w z++map(x:)(d#z);_#_=a;d%i=iterate((++)<*>((d#)=<<))[s]!!i=[i|i<-[k..],all(`elem`0%i)$1%k]!!0

Simple brute force solution. f takes a list of positive integers, and the DL-distance k.
This generates all strings up to the DL-distance limit k, and searches for the smallest L-distance that contains all of those strings (also by generating those strings). This saves bytes by using the same generator code for both types of distances.
Try it online! Note that this is too slow for some of the test cases, so the TIO version uses reduced test cases.
Pregolfed
Ungolfed version. Unlike the golfed version, this one removes duplicate strings during the generation, so it's also much faster:
import qualified Data.Set as S
import Data.List (sortBy)
import Data.Ord (comparing)

snub x = S.toList $ S.fromList x

f' s k =
  let -- 0 = any other symbol not in s
      alphabet = snub $ toEnum 0 : s
      -- all strings with L-distance 1 (if d, DL-distance)
      gen1 d s@(x:xs) = snub $ del ++ ins ++ sub ++ swap xs ++ map (x:) (gen1 d xs)
        where del = [xs]
              ins = map (:s) alphabet
              sub = map (:xs) alphabet
              swap (y:ys) | d = [y:x:ys]
              swap _ = []
      gen1 _ _ = map (:[]) alphabet
      -- as gen1, but distance <= i
      genAll d i = iterate (\x->snub $ x ++ (gen1 d =<< x)) [s] !! i
      -- strings with DL-distance <= k
      sDL = S.fromAscList $ genAll True k
  in head [ (i, worstStrings)
          | -- sL = genAll False i
            -- zip obtains sL' = genAll False (i-1) for calculating worstStrings
            ((_, sL'), (i, sL))
              <- zip <*> tail $ (,) <*> (S.fromAscList . genAll False) <$> [max 0(k-1)..],
            -- require that sL covers sDL
            sDL `S.isSubsetOf` sL,
            -- also show some maximal examples
            let interestingness t = length (filter (==toEnum 0) t) + abs (length t - length s)
                worstStrings =
                  take 5 $ sortBy (comparing interestingness) $
                  S.toList (sL `S.intersection` sDL `S.difference` sL')
            ]

Try it online! This uses the full testcases but Krypyp still times out on TIO (it takes a few minutes to solve). Also, it prints some of the strings that have maximal Levenshtein distance. Testcase solutions:
"hello", 3 -> 4 e.g. "eeeol","eehol","eeool","ehheo","ehhho"
"world", 2 -> 4 e.g. "owrdl"
"aaaaa", 1 -> 1 e.g. "_aaaa","a_aaa","aa_aa","aaa_a","aaaa"
"aaaaa", 2 -> 2 e.g. "__aaa","_a_aa","_aa_a","_aaa","_aaa_"
"abaaa", 3 -> 4 e.g. "aabbb","aab_b","aabb_","_aabab","_aabba"
"Krypyp", 3 -> 5 e.g. "rKyKppy","rKyppKy","rKyppry","rpKyppy","r_Kyppy"
"", 5 -> 5 e.g. "_____"

Java 11, 790 764 760 bytes
import java.util.*;t->n->{var S=new HashSet<String>();int m=n;for(;m>0;)p(S,"",t+"x".repeat(m--));for(var s:(HashSet<String>)S.clone())for(m=s.length()-n;m-->1;)S.add(s.substring(m));S.removeIf(s->d(1,s,t)!=n);for(var s:S)m=Math.max(d(0,s,t),m);return m;}void p(Set S,String p,String s){int l=s.length(),i=0;if(l<1)S.add(p);for(;i<l;)p(S,p+s.charAt(i),s.substring(0,i)+s.substring(++i));}int d(int f,String s,String t){int l=s.length()+1,L=t.length()+1,d[][]=new int[l][L],i=l,j,c,q,A,B;for(;i-->0;)d[i][0]=i;for(j=0;++j<L;)for(d[i=0][j]=j;++i<l;B=t.charAt(j-1),c=A==B?0:1,d[i][j]=q=Math.min(Math.min(d[i-1][j]+1,d[i][j-1]+1),d[i-1][j-1]+c),d[i][j]=f>0&i>1&j>1&&A==t.charAt(j-2)&s.charAt(i-2)==B?Math.min(q,d[i-2][j-2]+c):q)A=s.charAt(i-1);return d[l-1][L-1];}

Will golf it down (substantially I hope) from here.
Try it online.
Explanation:
General approach:
Input-String = t and input-integer = n in the explanation below.

Generate all permutations of t with up to n added characters, and add them to a Set
For each permutation, add a substring with up to n removed characters to the Set as well
Remove any String from this Set that does not have a Damerau-Levenshtein distance of n in comparison to t
Calculate the Levenshtein distance of each remaining String in comparison to t
Take the maximum, which is our result

Code explanation:
import java.util.*;               // Required import for the Set and HashSet

t->n->{                           // Method with String and integer parameters and integer return-type
  var S=new HashSet<String>();    //  Create a String-Set
  int m=n;for(;m>1;)              //  Loop `m` in the range [input-integer, 0):
    p(S,"",t                      //   Determine all permutations of the input-String
      +"x".repeat(m--));          //   With up to `m` additional "x" added
  for(var s:(HashSet<String>)S.clone())
                                  //  Loop over all generated permutations:
    for(m=s.length()-n;m-->1;)    //   Inner loop `m` in the range [permutation-length - input-integer, 1]:
      S.add(s.substring(m));      //    Add the permutation with the first `m` characters removed to the Set as well
                                  //  (NOTE: After these loops, `m` is 0 which we'll re-use later on)
  S.removeIf(s->                  //  Now remove any permutation from this Set which:
     d(1,s,t)!=n);                //   Does not have a DL-distance equal to the input-integer
  for(var s:S)                    //  Loop over all remaining Strings:
    m=Math.max(d(0,s,t),m);       //   Determine the maximum L-distance
  return m;}                      //  And return that maximum L-distance as result

// Separated recursive method to get all permutations from a String
void p(Set S,String p,String s){  // Method with Set and two String parameters and no return-type
int l=s.length(),                 //  Get the length of the input-String `s`
    i=0;                          //  Index-integer `i`, starting at 0
if(l<1)                           //  If the length is 0:
  S.add(p);                       //   Add the prefix-String `p` to the Set
for(;i<l;)                        //  Loop `i` in the range [0, length):
  p(S,p+s.charAt(i),              //   Append the `i`'th character to the prefix-String `p`
    s.substring(0,i)+s.substring(++i));}
                                  //   Remove the `i`'th character from the String `s`
                                  //   And do a recursive call

// Separated method to determine the DL or L distance of two Strings
int d(int f,String s,String t){   // Method with integer and two String parameters and String return-type
  int l=s.length()+1,             //  Length `l` of the source-String + 1
      L=t.length()+1,             //  Length `L` of the target-String + 1
      d[][]=new int[l][L],        //  Create an integer matrix of those dimensions
      i=l,j,                      //  Index-integers
      c,q,A,B;                    //  Temp integers
  for(;i-->0;)                    //  Loop `i` in the range (`l`, 0]:
    d[i][0]=i;                    //   Set the `i,0`'th cell to `i` in the matrix
  for(j=0;++j<L;)                 //  Loop `j` in the range [0, `L`):
    for(d[i=0][j]=j;              //   Set the `0,j`'th cell to `j` in the matrix
        ++i<l                     //   Inner loop `i` in the range [0, `l`):
        ;                         //     After every iteration:
         B=t.charAt(j-1),         //      Set `B` to the `j-1`'th character of the target-String
         c=A==B?                  //      If the characters `A` and `B` are the same:
            0                     //       Set `c` to 0
           :                      //      Else:
            1,                    //       Set `c` to 1
         d[i][j]=                 //      Set the `i,j`'th value to:
           q=Math.min(            //       The minimum of:
              Math.min(           //        The minimum of:
                d[i-1][j]+1,      //         The `i-1,j`'th value + 1
                d[i][j-1]+1),     //         And the `i,j-1`'th value + 1
              d[i-1][j-1]+c),     //        And the `i-1,j-1`'th value + `c`
         d[i][j]=                 //      Then, set the `i,j`'th value to:
                 f>0              //       If the given DL-flag is 1
                 &i>1&j>1         //       And both `i` and `j` are at least 2
                 &&A              //       And the character `A`
                   ==t.charAt(j-2)//       equals the `j-2`'th character in the target-String
                 &s.charAt(i-2)   //       And the `i-2`'th character in the source-String
                  ==B?            //       equals the character `B`:
                  Math.min(       //        Set the `i,j`'th value to the minimum of:
                   q,             //         The `i,j`'th value
                   d[i-2][j-2]+c) //         And the `i-2,j-2`'th value + `c`
                 :                //       Else (the given DL-flag is 0):
                  q)              //        Leave the `i,j`'th value the same
      A=s.charAt(i-1);            //    Set `A` to the `i-1`'th character of the source-String
  return d[l-1][L-l];}            //  Return the `l-1,L-1`'th value as result

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Historical difference between `/` and `÷` in mathematical expressions
Introduction:

Inspired by a discussion that is already going on for many years
  regarding the expression \$6÷2(1+2)\$.
With the expression \$6÷2(1+2)\$, mathematicians will quickly see that the correct answer is \$1\$, whereas people with a simple math background from school will quickly see that the correct answer is \$9\$. So where does this controversy and therefore different answers come from? There are two conflicting rules in how \$6÷2(1+2)\$ is written. One due to the part 2(, and one due to the division symbol ÷.
Although both mathematicians and 'ordinary people' will use PEMDAS (Parenthesis - Exponents - Division/Multiplication - Addition/Subtraction), for mathematicians the expression is evaluated like this below, because \$2(3)\$ is just like for example \$2x^2\$ a monomial a.k.a. "a single term due to implied multiplication by juxtaposition" (and therefore part of the P in PEMDAS), which will be evaluated differently than \$2×(3)\$ (a binomial a.k.a. two terms):
$$6÷2(1+2) → \frac{6}{2(3)} → \frac{6}{6} → 1$$
Whereas for 'ordinary people', \$2(3)\$ and \$2×(3)\$ will be the same (and therefore part of the MD in PEMDAS), so they'll use this instead:
$$6÷2(1+2) → 6/2×(1+2) → 6/2×3 → 3×3 → 9$$

However, even if we would have written the original expression as \$6÷2×(1+2)\$, there can still be some controversy due to the use of the division symbol ÷. In modern mathematics, the / and ÷ symbols have the exact same meaning: divide. Some rules pre-1918† regarding the division symbol ÷†† state that it had a different meaning than the division symbol /. This is because ÷ used to mean "divide the number/expression on the left with the number/expression on the right"†††. So \$a ÷ b\$ then, would be \$(a) / (b)\$ or \$\frac{a}{b}\$ now. In which case \$6÷2×(1+2)\$ would be evaluated like this by people pre-1918:
$$6÷2×(1+2) → \frac{6}{2×(1+2)} → \frac{6}{2×3} → \frac{6}{6} → 1$$
†: Although I have found multiple sources explaining how ÷ was
used in the past (see ††† below), I haven't been able to find
definitive prove this changed somewhere around 1918. But for the sake
of this challenge we assume 1918 was the turning point where ÷ and
/ starting to mean the same thing, where they differed in the past.

††: Other symbols have also been used in the past for division, like : in 1633 (or now still in The Netherlands and other European non-English speaking countries, since this is what I've personally learned in primary school xD) or ) in the 1540s. But for this challenge we only focus on the pre-1918 meaning of the obelus symbol ÷.
†††: Sources: this article in general. And the pre-1918 rules regarding ÷ are mentioned in: this The American Mathematical Monthly article from February 1917; this German Teutsche Algebra book from 1659 page 9 and page 76; this A First Book in Algebra from 1895 page 46 [48/189].
Slightly off-topic: regarding the actual discussion about this
  expression: It should never be written like this in the first
  place! The correct answer is irrelevant, if the question is unclear.
  *Clicks the "close because it's unclear what you're asking" button*.
  And for the record, even different versions of Casio
  calculators don't know how to properly deal with this expression:

Challenge:
You are given two inputs:

A (valid) mathematical expression consisting only of the symbols 0123456789+-×/÷()
A year

And you output the result of the mathematical expression, based on the year (where ÷ is used differently when \$year<1918\$, but is used exactly the same as / when \$year\ge1918\$).
Challenge rules:

You can assume the mathematical expression is valid and only uses the symbols 0123456789+-×/÷(). This also means you won't have to deal with exponentiation. (You are also allowed to use a different symbols for × or ÷ (i.e. * or %), if it helps the golfing or if your language only supports ASCII.)
You are allowed to add space-delimiters to the input-expression if this helps the (perhaps manual) evaluation of the expression.
I/O is flexible. Input can be as a string, character-array, etc. Year can be as an integer, date-object, string, etc. Output will be a decimal number.
You can assume there won't be any division by 0 test cases.
You can assume the numbers in the input-expression will be non-negative (so you won't have to deal with differentiating the - as negative symbol vs - as subtraction symbol). The output can however still be negative!
You can assume N( will always be written as N×( instead. We'll only focus on the second controversy of the division symbols / vs ÷ in this challenge.
Decimal output-values should have a precision of at least three decimal digits.
If the input-expression contains multiple ÷ (i.e. \$4÷2÷2\$) with \$year<1918\$, they are evaluated like this: \$4÷2÷2 → \frac{4}{\frac{2}{2}} → \frac{4}{1} → 4\$. (Or in words: number \$4\$ is divided by expression \$2 ÷2\$, where expression \$2 ÷2\$ in turn means number \$2\$ is divided by number \$2\$.)
Note that the way ÷ works implicitly means it has operator precedence over × and / (see test case \$4÷2×2÷3\$).
You can assume the input-year is within the range \$[0000, 9999]\$.

General rules:

This is code-golf, so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
Default Loopholes are forbidden.
If possible, please add a link with a test for your code (i.e. TIO).
Also, adding an explanation for your answer is highly recommended.

Test cases:
Input-expression:   Input-year:   Output:      Expression interpretation with parenthesis:

6÷2×(1+2)           2018          9            (6/2)×(1+2)
6÷2×(1+2)           1917          1            6/(2×(1+2))
9+6÷3-3+15/3        2000          13           ((9+(6/3))-3)+(15/3)
9+6÷3-3+15/3        1800          3            (9+6)/((3-3)+(15/3))
4÷2÷2               1918          1            (4/2)/2
4÷2÷2               1900          4            4/(2/2)
(1÷6-3)×5÷2/2       2400          -3.541...    ((((1/6)-3)×5)/2)/2
(1÷6-3)×5÷2/2       1400          1.666...     ((1/(6-3))×5)/(2/2)
1×2÷5×5-15          2015          -13          (((1×2)/5)×5)-15
1×2÷5×5-15          1719          0.2          (1×2)/((5×5)-15)
10/2+3×7            1991          26           (10/2)+(3×7)
10/2+3×7            1911          26           (10/2)+(3×7)
10÷2+3×7            1991          26           (10/2)+(3×7)
10÷2+3×7            1911          0.434...     10/(2+(3×7))
4÷2+2÷2             2000          3            (4/2)+(2/2)
4÷2+2÷2             1900          2            4/((2+2)/2)
4÷2×2÷3             9999          1.333...     ((4/2)×2)/3
4÷2×2÷3             0000          3            4/((2×2)/3)
((10÷2)÷2)+3÷7      2000          2.928...     ((10/2)/2)+(3/7)
((10÷2)÷2)+3÷7      1900          0.785...     (((10/2)/2)+3)/7
(10÷(2÷2))+3×7+(10÷(2÷2))+3×7
                    1920          62           (10/(2/2))+(3×7)+(10/(2/2))+(3×7)
(10÷(2÷2))+3×7+(10÷(2÷2))+3×7
                    1750          62           (10/(2/2))+(3×7)+(10/(2/2))+(3×7)
10÷2/2+4            2000          6.5          ((10/2)/2)+4
10÷2/2+4            0100          2            10/((2/2)+4)
9+6÷3-3+15/3        9630          13           9+(6/3)-3+(15/3)
9+6÷3-3+15/3        0369          3            (9+6)/(3-3+(15/3))

R, 68 66 bytes
function(x,y,`=`=`/`)eval(parse(t=`if`(y<1918,x,gsub('=','/',x))))

Try it online!
Expects equality sign = instead of ÷ and * instead of ×.
The code makes use of some nasty operator overloading, making advantage of the fact that = is a right-to-left operator with very low precedence (the exact behavior that we want from pre-1918 ÷), and R retains its original precedence when it is overloaded. The rest is automatically done for us by eval.
As a bonus, here is the same exact approach implemented in terser syntax. This time our special division operator is tilde (~):
Julia 0.7, 51 bytes
~=/;f(x,y)=eval(parse(y<1918?x:replace(x,'~','/')))

Try it online!

\=`=`/`` is diabolical! Great solution!

uuugggghhh I had thoughts on the same lines. Alas, you beat me to it by quite a lot. Try it online

Although there are no answers in codegolf languages yet, I'm accepting your Julia answer as the shortest for now. It is possible this will change in the future of course if a shorter answer is posted.

JavaScript (ES6),  130 129  120 bytes
Saved 9 bytes thanks to @ScottHamper
Takes input as (year)(expr). Expects % and * instead of ÷ and ×.
y=>g=e=>(e!=(e=e.replace(/\([^()]*\)/,h=e=>eval(e.split`%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))))?g:h)(e)

Try it online!
How?
Processing leaf expressions
The helper function \$h\$ expects a leaf expression \$e\$ as input, processes all % symbols according to the rules of the year \$y\$ (defined in the parent scope) and evaluates the resulting string.
If \$y<1918\$, we transform X%Y into (X)/(Y), to enforce low precedence and repeat this process for the entire string from right to left to enforce right-to-left associativity.
Examples:

8%2 becomes (8)/(2), whose simplified form is 8/2
2+3%3+2 becomes (2+3)/(3+2)
8%2%2 becomes (8)/((2)/(2)), whose simplified form is 8/(2/2)

If \$y\ge 1918\$, each % is simply turned into a /.
h = e =>                    // e = input string
  eval(                     // evaluate as JS code:
    e.split`%`              //   split e on '%'
    .reduceRight((a, c) =>  //   for each element 'c', starting from the right and
                            //   using 'a' as the accumulator:
      y < 1918 ?            //     if y is less than 1918:
        `(${c})/(${a})`     //       transform 'X%Y' into '(X)/(Y)'
      :                     //     else:
        c + '/' + a         //       just replace '%' with '/'
    )                       //   end of reduceRight()
  )                         // end of eval()

Dealing with nested expressions
As mentioned above, the function \$h\$ is designed to operate on a leaf expression, i.e. an expression without any other sub-expression enclosed in parentheses.
That's why we use the helper function \$g\$ to recursively identify and process such leaf expressions.
g = e => (            // e = input
  e !=                // compare the current expression with
    ( e = e.replace(  // the updated expression where:
        /\([^()]*\)/, //   each leaf expression '(A)'
        h             //   is processed with h
      )               // end of replace()
    ) ?               // if the new expression is different from the original one:
      g               //   do a recursive call to g
    :                 // else:
      h               //   invoke h on the final string
)(e)                  // invoke either g(e) or h(e)

Here's a version of h that's 9 bytes shorter: h=e=>eval(e.split\%`.reduceRight((a,c)=>y<1918?`(${c})/(${a})`:c+'/'+a))`

@ScottHamper Very nice. 'Right to left' should have ring a bell ... but it didn't.

Python 3.8 (pre-release), 324 310 306 bytes
lambda s,y:eval((g(s*(y<1918))or s).replace('%','/'))
def g(s):
 if'%'not in s:return s
 l=r=j=J=i=s.find('%');x=y=0
 while j>-1and(x:=x+~-')('.find(s[j])%3-1)>-1:l=[l,j][x<1];j-=1
 while s[J:]and(y:=y+~-'()'.find(s[J])%3-1)>-1:r=[r,J+1][y<1];J+=1
 return g(s[:l]+'('+g(s[l:i])+')/('+g(s[i+1:r])+')'+s[r:])

Try it online!
Takes % instead of ÷ and * instead of ×

Perl 5, 47 97 95 bytes

/ /;$_="($`)";$'<1918?s-%-)/(-g:y-%-/-;$_=eval

$_="($F[0])";1while$F[1]<1918&&s-\([^()]+\)-local$_=$&;s,%,)/((,rg.")"x y,%,,-ee;y-%-/-;$_=eval

TIO

Very nice idea. However, you have an issue with 4%2%2 which returns 1 in both cases. (whereas it should return 4 pre-1918)

it's true, i can't look anymore for the moment

@Dada, fixed (+50bytes)

Rust - 1066 860 783 755 740 bytes
macro_rules! p{($x:expr)=>{$x.pop().unwrap()}}fn t(s:&str,n:i64)->f64{let (mut m,mut o)=(vec![],vec![]);let l=|v:&Vec<char>|*v.last().unwrap();let z=|s:&str|s.chars().nth(0).unwrap();let u=|c:char|->(i64,fn(f64,f64)->f64){match c{'÷'=>(if n<1918{-1}else{6},|x,y|y/x),'×'|'*'=>(4,|x,y|y*x),'-'=>(2,|x,y|y-x),'+'=>(2,|x,y|y+x),'/'=>(5,|x,y|y/x),_=>(0,|_,_|0.),}};macro_rules! c{($o:expr,$m:expr)=>{let x=(u(p!($o)).1)(p!($m),p!($m));$m.push(x);};};for k in s.split(" "){match z(k){'0'..='9'=>m.push(k.parse::<i64>().unwrap() as f64),'('=>o.push('('),')'=>{while l(&o)!='('{c!(o,m);}p!(o);}_=>{let j=u(z(k));while o.len()>0&&(u(l(&o)).0.abs()>=j.0.abs()){if j.0<0&&u(l(&o)).0<0{break;};c!(o,m);}o.push(z(k));}}}while o.len()>0{c!(o,m);}p!(m)}

Rust does not have anything like 'eval' so this is a bit tough. Basically, this is a bog-standard Djisktra shunting-yard infix evaluator with a minor modification. ÷ is an operator with a variable precedence: lower than everything else (but parenthesis) in <1918 mode, higher than everything else in >=1918 mode. It is also 'right associated' (or left?) for <1918 to meet the 4÷2÷2 specification, and association is 'faked' by making ÷ precedence negative, then during evaluation treating any precedence <0 as associated. There's more room for golfing but this is a good draft i think.
Ungolfed at play.rust-lang.org

Do you really need that much whitespace? I think most of it could be removed.

@ivzem good point, but still its 3 times bigger than python

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Implement MENACE
Background
MENACE (Machine Educable Noughts And Crosses Engine) is a rudimentary shallow machine learning algorithm for the game Noughts and Crosses, created by British computer scientist Donald Michie in the 1960s. It was originally implemented with 304 matchboxes, each labelled with a board position and containing coloured beads (with one of nine colours, representing possible moves). Michie calculated that these 304 matchboxes were enough for every combination of moves on the board.
The more mathematical among you may realise that there are actually 19,683 possible combinations of Noughts, Crosses and Blanks on a N&C board; however, he calculated ways to cut down on this number (to speed up the algorithm, and likely to cut down on matchboxes!). Firstly, he removed all none-possible moves, such as:
-------
|X|0|X|
| |0| |
|X|X| |
-------

(two noughts and four crosses)
Next, he compensated for rotations. For instance, if on the matchbox we see:
-------
| |0|0|
|X| |X|
| |0| |
-------

we can use the same box for
-------
| |X| |
|0| |0|
| |X|0|
-------

Therefore, the aforementioned coloured beads represent relative positions, not absolute ones. For instance, if we said that a red bead meant top-left, then we'd take a look at the image on the top of the box and see:
-------
| |0|0|
|X| |X|
| |0| |
-------

so we'd know that in the case that this is the board, then the red bead would mean:
-------
|R|0|0|
|X| |X|
| |0| |
-------

But if this is the board:
-------
| |X| |
|0| |0|
| |X|0|
-------

the red bead would mean
-------
| |X|R|
|0| |0|
| |X|0|
-------

These transformations applied for rotations and inverting (in all directions, including diagonal). Once again, you only need to save each matchbox once this way: do not make separate virtual boxes for each transformation!
Another simplification Michie made was to make sure the computer goes first. This way, he could remove all first-level moves, removing about a fifth of the remaining boxes. Finally, he removed all game-ending boxes (as no further 'contents' or moves were required on these steps).
Right, now onto the algorithm itself (it's very simple):

First, decide on what the colours of the beads represent. You'll need 9 colours to represent each of the spaces on the board.
At the start of the game, each of the 304 matchboxes contains beads. While the beads are of random colour (so duplicates are fine), they should be possible moves (so if the board state image depicts an 'O' in the middle-right, then you can't use the bead that represents the middle-right).
Every time it is MENACE's (X) turn, find the matchbox with the current board position (or some transformation of it) printed onto it.
Open the matchbox, and choose any bead in there at random.
Find how the board status has been transformed to get to the image on the matchbox (e.g rotated 90deg anticlockwise). Then, apply that transformation to the bead (e.g top-left becomes left-left).
Place an X in that square. Remove the selected bead from the matchbox. If the box is left empty as a result, put three random (possible) beads into the box, and pick one of them for the move.
Repeat 3-6 until the game is over.
If MENACE won the game, go back through every matchbox MENACE took. Then, trace back what colour bead it used on that move. Put two of that colour of bead into the box (so that there is the original bead + one more, thereby increasing the likelyhood of MENACE making that move next time it gets to that position)
If MENACE lost the game, do nothing (don't replace the beads it took out).
If MENACE drew the game, then replace the bead it used in each of its moves, but don't add an extra one, so that you're left with what you started.

This leaves us with an algorithm that is very simple, but difficult to implement. This forms the basis of your challenge.
If you're still confused, see http://chalkdustmagazine.com/features/menace-machine-educable-noughts-crosses-engine/ - it's what I read when I first learned about this algorithm
Challenge
Play a game of Tic-Tac-Toe with the computer. At each step, output the contents of all of the matchboxes.
Inputs

At the start of the program a number, saying how many games you want to play against MENACE
Then, after MENACE's first turn, you input your move as a two character string, the first letter being "L", "R", or "M" (left, right or middle) referring to the Y axis. Then you input another letter (again, "L", "R", or "M"), this time referring to the X axis. Repeat for all moves and games.

Outputs

At the start of each new game, output "new game".
After each move by the player, output the board in any reasonable format. It doesn't need to look pretty (e.g an array of arrays representing the positions of the board is fine).
After each move by the player, MENACE should make a move. Output the board after MENACE's move
After each game, output the contents of all 304 matchboxes. Beads can be represented by a letter, name of a colour, character or whatever string or integer you like (no pointers, anonymous functions, etc).

Rules

This is code-golf, so shortest answer in bytes wins.
I must be able to input moves after seeing MENACE's response. No 'pass all of your moves into this function, and watch how the game plays out'.
The board must be cleared between games.
The matchboxes must not be cleared between games (this would reset the machine learning)
You must have 304 matchboxes. Anyone can implement this algorithm with all 19,683 matchboxes, but the learning is slow (as it requires lots of games to get all of them with useful contents).
The output can be in any reasonable format, and input can be taken as per PPCG standards (as long as it complies with rule 2). If you need to adjust the input format (as described in the 'Input' section) then it's OK as long as it makes sense.
A game ends when a player wins (by getting three in a row diagonally, horizontally or vertically) or if there is a draw (the board is full and there is no winner)
While MENACE needs to make possible moves (and only have possible beads inside each matchbox), for the sake of the challenge you don't need to validate the input of the user. If they type in something wrong, your program can do whatever (go completely crazy, throw error, etc.) - you can assume that the input is correct.

I remember Martin Gardner demonstrating the idea using the simpler game Hexapawn, although I forget what he named the "computer" that he constructed.

@Neil https://personalpages.manchester.ac.uk/staff/Andrew.Hazel/learning_machine/learning_machine.html maybe?

https://www.youtube.com/watch?v=R9c-_neaxeU

Great challenge. Couple of quick questions: 1. Once there is more than one bead in a given space in a box, how should that be represented in the output?  2. Do you really want all 304 boxes (2736 cells) output after each move?

@NickKennedy Thanks for the feedback. The way I'd expect the beads to be represented when it's logged is as an array (though you can do it differently to not restrict different languages), e.g if you chose numbers to represent the beads: [[0, 2, 6], [4, 8, 4, 3, 3], [7, 7, 7, 7, 7, 7, 7, 8], [1], ... [3, 3, 5, 4]].

The only reason I'd like to output the matchboxes is because I read in the 'Things to avoid in a challenge' Meta question that you shouldn't write 'Implement this algorithm' as a challenge in itself - let people figure out their own logic/adaptation of the problem.  This way, the problem is 'When given these inputs, give an output following this logic'. However, I've edited the question to only output the matchboxes at the end of each game just to neaten the output a bit more.

Am I skimming a rule or is the number of beads at the beginning never defined anywhere? I see in the article it's the box representing Menace’s first turn had four beads for each different move. The boxes representing the layouts of the board for Menace’s second turn contained three beads for each different move; there were two beads each for Menace’s third; and one of each in the boxes representing Menace’s fourth go. Is this the case here?

@Veskah no, it can have from 1-9 beads.

R, 839 bytes
options(max.print=1e5)
s=colSums
r=rowSums
m=matrix
a=array
y=apply
S=sum
p=sample
b=m(rep(i<-1:(K=3^9),e=9)%/%(E=3^(8:0))%%3,c(9,K))
V=a(1:9,c(3,3,8))
V[,,2:4]=c(V[x<-3:1,,1],V[,x,1],V[x,x,1])
V[,,5:8]=y(V[,,1:4],3,t)
d=aperm(a(b[c(V),],c(9,8,K)),c(1,3,2))
v=m(V,9)
g=y(m(match(e<-y(d*E,2:3,S),i),,8),1,min)
g[K]=K
G=9-y(t(e==g)*8:1,2,max)
h=s(a(c(b,d[,,5],b[c(1,5,9,3,5,7,1:3),]),c(3,3,K,3))*3^(0:2))
k=r(s(h==13))>0
l=r(s(h==26))>0
o=s(b>0)
M=b
M[M==0]=-1
repeat{A=b[,t<-K]
z=j=c();B=1
repeat{if(S(pmax(-M[,t],0))<1)M[p(9,pmin(3,S(x)),,x<-M[,t]<1),t]=-1
z=c(z,u<-p(9,1,,pmax(-M[,t],0)))
j=c(j,t)
A[v[,G[B]][u]]=1
print(m(A,3))
if(k[B<-S(A*E)]||o[B]==9)break
A[ceiling((utf8ToInt(readline())-76)/5)%*%c(1,3)+1]=2
if(l[B<-S(A*E)])break
t=g[B]}
M[x]=M[x<-cbind(z,j)]-k[B]+l[B]
print(a(M[,g==seq(g)&!k&!l&s(b==1)==s(b==2)&o<8],c(3,3,304)))}

Try it online!
Quite a long answer, but this wasn't a straightforward challenge. The TIO link here will fail because it expects interactive input. Here's a version that plays against a second, random player who just picks a spot at random. The output for this second version is just the winner (1, 2 or 0 for a draw.) Matchboxes are initialised for all board positions, but only used for the 304 per the spec. They're implemented as copies of the board with negative numbers to indicate the number of beads on each position. I experimented with a list of vectors per the original spec, but it was less intuitive.
This is a less golfed version with comments (but still short variable names). Note that it doesn't print the matchboxes out because they're very long. It can implement an interactive player 2, a random player 2 or the same matchbox strategy for player 2.
auto = 1 # 1 = Random player 2, 2 = Player 2 uses learning strategy
         # 0 for interactive
print_board <- function(board) {
  cat(apply(matrix(c(".", "X", "O")[board + 1], 3), 1, paste, collapse = ""), "", sep = "\n")
}
E = 3 ^ (8:0) # Number of possible arrangements of board
              # ignoring rotations etc.
# Make all possible boards
b = matrix(rep(1:3 ^ 9, e = 9) %/% E %% 3, c(9, 3 ^ 9))
# Define the eight possible rotation/inversion matrices
V = array(1:9, c(3, 3, 8))
V[, , 2:4] = c(V[x <- 3:1, , 1], V[, x, 1], V[x, x, 1])
V[, , 5:8] = apply(V[, , 1:4], 3, t)
# Create eight copies of the 19683 boards with each transformation
d = aperm(array(b[c(V), ], c(9, 8, 3 ^ 9)), c(1, 3, 2))
v = matrix(V, 9)
# Create reverse transformations (which are the same except for rotation)
w = v[, c(1:5, 7, 6, 8)]
# Find the sums of each transformation using base 3
e = apply(d * E, 2:3, sum)
# Find the lowest possible sum for each board's transformed versions
# This will be the one used for the matchboxes
f = matrix(match(e, 1:3 ^ 9), , 8)
g = apply(f, 1, min)
# Store which transformation was necessary to convert the lowest board
# into this one
G = 9 - apply(t(e == g) * 8:1, 2, max)
# Work out which boards have 3-in-a-row
h = colSums(array(c(b, d[, , 5], b[c(1, 5, 9, 3, 5, 7, 1:3), ]), c(3, 3, 3 ^ 9, 3)) * 3 ^ (0:2))
k = rowSums(colSums(h == 13)) > 0 # player 1 wins
l = rowSums(colSums(h == 26)) > 0 # player 2 wins
# Store how many cells are filled
o = colSums(b > 0)
# Create matchboxes. These contain the actual board configuration, but
# instead of zeroes for blanks have a minus number. This is initially -1,
# but will ultimately represent the number of beads for that spot on the
# board.
M = b
M[M == 0] = -1
repeat {
  # Initialise board and storage of moves and intermediate board positions
  A = b[, t <- 3 ^ 9]
  z = j = c()
  C = 1
  # If we're automating player 2 also, initialise its storage
  if (auto) {
    Z = J = c()
  }
  repeat {
    # If the current board's matchbox is empty, put up to three more beads
    # back in
    if (sum(pmax(-M[, t], 0)) == 0) {
      M[sample(9, pmin(3, sum(x)), , x <- M[, t] == 0), t] = -1
    }
    # Take out a bead from the matchbox
    u = sample(9, 1, , pmax(-M[, t], 0))
    # Mark the bead as taken out
    M[u, t] = M[u, t] + 1
    # Store the bead and board position in the chain for this game
    z = c(z, u)
    j = c(j, t)
    # Mark the spot on the board
    A[v[, C][u]] = 1
    # Print the board
    if (!auto) print_board(matrix(A, 3))
    # Check if  player 1 has won or board is full
    if (k[B <- sum(A * E)] || o[B] == 9) break
    if (auto) {
      # Repeat for player 2 if we're automating its moves
      # Note if auto == 1 then we pick at random
      # If auto == 2 we use the same algorithm as player 1
      D = g[B]
      if (sum(pmax(-M[, D], 0)) == 0) {
        M[sample(9, pmin(3, sum(x)), , x <- M[, D] == 0), D] = -1
      }
      U = sample(9, 1, , if (auto == 1) M[, D] <= 0 else pmax(-M[, D], 0))
      Z = c(Z, U)
      J = c(J, D)
      A[v[, G[B]][U]] = 2
    } else {
      cat(
        "Please enter move (LMR for top/middle/bottom row and\nLMR for left/middle/right column, e.g. MR:"
      )
      repeat {
        # Convert LMR into numbers
        q = ceiling((utf8ToInt(readline()) - 76) / 5)
        if (length(q) != 2)
          stop("Finished")
        if (all(q %in% 0:2) && A[q %*% c(1, 3) + 1] == 0) {
          break
        } else {
          message("Invalid input, please try again")
        }
      }
      A[q %*% c(1, 3) + 1] = 2
    }
    if (l[B <- sum(A * E)])
      break
    # Player 2 has won
    t = g[B]
    C = G[B]
  }
  if (auto) {
    cat(c("D", 1:2)[1 + k[B] + 2 * l[B]])
  } else {
    cat("Outcome:", c("Draw", sprintf("Player %d wins", 1:2))[1 + k[B] + 2 * l[B]], "\n")
  }
  # Add beads back to matchbox
  M[x] = M[x <- cbind(z, j)] - k[B] - 1 + l[B]
  if (auto)
    M[x] = M[x <- cbind(Z, J)] - l[B] - 1 + k[B]
}

Very clever! Of course, the rotations make it difficult, but thanks for adding the bot player as well!