View version with tabs instead of spaces.
-------------------
<?php

// Run all code on this page if the $_POST variables are set.
if (isset($_POST['user_page_title']) && isset($_POST['html_content']) && isset($_POST['submit']) && empty($_POST['hola'])) {

$user_page_title strip_tags($_POST['user_page_title']);
$html_content strip_tags($_POST['html_content']);

function 
error_message($error_message_content) {
    echo 
'<div class="error-message">'.$error_message_content.'</div>';
}

// Make sure there are no URLs.
$url_words = array('www','http','https','ftp','sftp','src');
foreach (
$url_words as $w) {
    if ((
strpos($user_page_title$w) !== false) || (strpos($html_content$w) !== false)) {
        
error_message("URLs are not allowed in the submission content. Please contact me if you need an exception.");
        return;
    }
}

// Make sure they agree with terms. This is done as well with Javascript, but this is a backup.
if (!isset($_POST['agreement'])) {
    
error_message("Please agree to the Acceptable Use Policy before submission.");
    return;
}

// Make sure title is not too long.
if(strlen($user_page_title)>150) {
    
error_message("The title must be 150 characters or fewer.");
    return;
}

// Make sure content is not too long.
if(strlen($html_content)>7000) {
    
error_message("The input must be 7,000 characters or fewer.");
    return;
}

// Reject submission if there is foul language. Please contact me if you would like to have the list.php source file.
$all_user_data $user_page_title.' '.$html_content;
include 
'list.php';
if (
preg_match("#\b($list)\b#"$all_user_data)) {
    
error_message("Profanity is not allowed.");
    return;
}

// Make sure no field is empty. This is also run client-side with Javascript, but this is a backup in case Javascript is disabled.
if(empty($user_page_title) || empty($html_content)) {
    
error_message("A content field is empty.");
    return;
}

// Take all items in square brackets and add them to an array called $items.
preg_match_all('/\[([^\]]+)\]/'$html_content$items);

// Make sure there are square brackets, an equal number of square brackets, and that there are not formatting errors with square brackets.
$num_opening substr_count($html_content,'[');
$num_closing substr_count($html_content,']');
if((
$num_opening == 0) && ($num_closing == 0)) {
    
error_message("There are no square brackets. Please review your text.");
    return;
}
if(
$num_opening !== $num_closing) {
    
error_message("There is an unequal number of square brackets. Please review your text.");
    return;
}
if(
$num_opening !== count($items[0])) {
    
error_message("There is a formatting error with your square brackets. Please review your text.");
    return;
}

$header_content = <<<HEAD
<!DOCTYPE html>
<html lang="en">
<!-- This practice sheet was created using worksheetmaker.net. -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
p.main_paragraph { line-height: 3em; }
input[type="text"] { border: 1px solid #aaa; padding: 5px; font-size: 1em; width: 175px; }
input[type="button"] { border: 1px solid #aaa; padding: 5px; font-size: 1em; width: 175px; }
body { margin: 25px; font-family: sans-serif; }
</style>
<title>
$user_page_title</title>
</head>
<body>
<h1>
$user_page_title</h1>
HEAD;

// Create worksheet URL from page title. This includes the path and filename. Weird characters and spaces are replaced by dashes. It is put into lower case with the date to the second.
$fname '1/'.str_replace(str_split('\\/:*?!#$%^&()"<>| '), '-'strtolower($user_page_title)).'_'.date("Y-m-d_H-i-s").'.htm';

// Set these so I do not get an undefined variable error when appending.
$jav_vars '';
$jav_if_statements '';

// This number will increment and is placed at the end of the html id and Javascript variables to ensure it is unique.
$num 1;
// Loop through each set of items within square brackets.
foreach ($items[1] as $i) {
    
// Get html id. Make it alpha numeric and append $num to the end.
    
$html_id '_'.preg_replace("/[^[:alnum:]]/u"''strtolower("{$i}{$num}"));
    
// Replace the first instance found of square brackets with the html input field. preg_replace updates the $html_content variable.
    
$html_content preg_replace('/\[([^\]]+)\]/''<input type="text" id="' $html_id '"><span id="check_' $html_id '"></span>'$html_content1);
    
// Javascript variables use the html id above as well.
    
$jav_vars .= 'var '.$html_id.' = document.getElementById(\''.$html_id.'\').value.toLowerCase().replace(/^\s\s*/, \'\').replace(/\s\s*$/, \'\');'."\n";
    
// Javascript if statements
    // Make the user's answers not caps sensitive.
    
$answer_options strtolower($i);
    
// Count answer options based on number of commas. There is no comma after the last item so 1 is added.
    
$num_answer_options substr_count($answer_options,",") + 1;
    
// Make $answer_options an array.
    
$answer_options = (explode(",",$answer_options));
    
// Take out white space.
    
$answer_options array_map('trim',$answer_options);
    
// I can't think of a scenario where someone would have more than five accepted answers.
    
if ($num_answer_options 5) {
        
error_message("Too many vocab items. Please use five or fewer.");
        return;
    }
    
// Use php if statements to create Javascript if statements. Each value is appended to the $jav_if_statements variable. There is a lot of concatenation of variable content (php) with string content (Javascript).
    
if ($num_answer_options == 5) {
        
$jav_if_statements .= 'if ('.$html_id.' == "'.$answer_options[0].'" || '.$html_id.' == "'.$answer_options[1].'" || '.$html_id.' == "'.$answer_options[2].'" || '.$html_id.' == "'.$answer_options[3].'" || '.$html_id.' == "'.$answer_options[4].'") {';
    }
    if (
$num_answer_options == 4) {
        
$jav_if_statements .= 'if ('.$html_id.' == "'.$answer_options[0].'" || '.$html_id.' == "'.$answer_options[1].'" || '.$html_id.' == "'.$answer_options[2].'" || '.$html_id.' == "'.$answer_options[3].'") {';
    }
    if (
$num_answer_options == 3) {
        
$jav_if_statements .= 'if ('.$html_id.' == "'.$answer_options[0].'" || '.$html_id.' == "'.$answer_options[1].'" || '.$html_id.' == "'.$answer_options[2].'") {';
    }
    if (
$num_answer_options == 2) {
        
$jav_if_statements .= 'if ('.$html_id.' == "'.$answer_options[0].'" || '.$html_id.' == "'.$answer_options[1].'") {';
    }
    if (
$num_answer_options == 1) {
        
$jav_if_statements .= 'if ('.$html_id.' == "'.$answer_options[0].'") {';
    }
        
// I did not want to repeat this under each php if statement because it is the same regardless of the number of items.
        
$jav_if_statements .= 'check_'.$html_id.'.innerHTML = bien;
           num_right++;
        } else {
           check_'
.$html_id.'.innerHTML = ojo;
        }
           num_total++;'
."\n";
    
$num++;
}

// Replace carriage returns and newlines with line break tags.
$html_content '<p class="main_paragraph">'.preg_replace("/\r\n|\r|\n/",'<br>',$html_content).'</p>';

// Start of Javascript
$jav_start = <<<JAV_START
<p><input type="button" value="Check answers" onclick="check_answers()"></p>
<p id="number_correct"></p>
<script>
function check_answers() {
var bien = '<span style="color: green;"> &#10004;</span>';
var ojo = '<span style="color: red;"> &#10006;</span>';
var num_right = 0;
var num_total = 0;
JAV_START;

// This is where the Javascript variables and if statements will go in the generated practice. See $all_page_data below.

// End of Javascript
$jav_end = <<<JAV_END
document.getElementById('number_correct').innerHTML = "You scored "+num_right+"/"+num_total+".";
}
document.onkeydown = function(e) {
if (e.code === "Enter") {
        check_answers(e);
    }
}
</script>
</body>
</html>
JAV_END;

$all_page_data $header_content."\n".$html_content."\n".$jav_start."\n".$jav_vars.$jav_if_statements.$jav_end;
include 
'usage.php';
file_put_contents($fname$all_page_data);
file_get_contents('https://ntfy.sh/xzqUulIXj88R'falsestream_context_create([
    
'http' => [
    
'method' => 'PUT'// PUT also works
    
'header' => 'Content-Type: text/plain',
    
'content' => 'Someone used worksheetmaker.net.'
    
]
]));
echo 
'<div class="submission-links"><span style="color: green; font-size: 3em; margin-right: 10px; vertical-align: -3px;">✔</span><span style="font-size: 1.5em; vertical-align: text-bottom;"><a href="'.$fname.'" download>Download File</a></span><br><span>Generated files are removed after 24 hours.</span></div>';
}

?>