Skip to content
Merged
49 changes: 49 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,55 @@ else
((PASSED++))
fi

# Test: mk template python
cd "$TEST_DIR"
u7 mk template python myapp >/dev/null 2>&1
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" ]]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test for the Python template is incomplete. The scaffolding logic creates src/__init__.py, but this check doesn't verify its existence. Adding this check will make the test more thorough and prevent future regressions.

Suggested change
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" ]]; then
if [[ -f "myapp/src/main.py" && -f "myapp/README.md" && -f "myapp/tests/__init__.py" && -f "myapp/src/__init__.py" ]]; then

echo -e "${GREEN}✓${NC} mk template python works"
((PASSED++))
else
echo -e "${RED}✗${NC} mk template python failed"
((FAILED++))
fi

# Test: mk template node
u7 mk template node mynode >/dev/null 2>&1
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" ]]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test for the Node.js template is incomplete. The scaffolding logic also creates a README.md file and a test directory, but this test doesn't verify their existence. Expanding the check will make the test more robust.

Suggested change
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" ]]; then
if [[ -f "mynode/package.json" && -f "mynode/src/index.js" && -f "mynode/README.md" && -d "mynode/test" ]]; then

assert_contains "mk template node package.json has name" "mynode" "$(cat mynode/package.json)"
else
echo -e "${RED}✗${NC} mk template node failed"
((FAILED++))
fi

# Test: mk template bash
u7 mk template bash mybash >/dev/null 2>&1
if [[ -f "mybash/main.sh" && -x "mybash/main.sh" ]]; then
echo -e "${GREEN}✓${NC} mk template bash works"
((PASSED++))
else
echo -e "${RED}✗${NC} mk template bash failed"
((FAILED++))
fi

# Test: mk template web
u7 mk template web myweb >/dev/null 2>&1
if [[ -f "myweb/index.html" && -d "myweb/css" && -d "myweb/js" ]]; then
echo -e "${GREEN}✓${NC} mk template web works"
((PASSED++))
else
echo -e "${RED}✗${NC} mk template web failed"
((FAILED++))
fi

# Test: mk template requires args
result=$(u7 mk template 2>&1)
assert_contains "mk template requires args" "Usage:" "$result"

# Test: mk template rejects existing directory
mkdir -p existing_dir
result=$(u7 mk template python existing_dir 2>&1)
assert_contains "mk template rejects existing dir" "already exists" "$result"

# Cleanup
cd /
rm -rf "$TEST_DIR"
Expand Down
55 changes: 55 additions & 0 deletions utility.sh
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,60 @@ _u7_make() {
fi
;;

template)
local tmpl="$1"
local name="$2"
if [[ -z "$tmpl" || -z "$name" ]]; then
echo "Usage: u7 mk template <python|node|bash|web> <project-name>"
return 1
fi
if [[ "$name" == *..* || "$name" == /* ]]; then
echo "Error: project name must not contain '..' or start with '/'"
return 1
fi
if [[ -d "$name" ]]; then
echo "Error: directory '$name' already exists"
return 1
fi
if [[ "$_U7_DRY_RUN" == "1" ]]; then
echo "[dry-run] Create $tmpl project: $name"
return 0
fi
case "$tmpl" in
python)
mkdir -p "$name/src" "$name/tests"
echo "# $name" > "$name/README.md"
echo "#!/usr/bin/env python3" > "$name/src/main.py"
touch "$name/src/__init__.py" "$name/tests/__init__.py"
echo "Created Python project: $name"
;;
node)
_u7_require jq || return 1
mkdir -p "$name/src" "$name/test"
echo "# $name" > "$name/README.md"
jq -n --arg name "$name" '{"name": $name, "version": "0.1.0", "main": "src/index.js"}' > "$name/package.json"
echo "// $name" > "$name/src/index.js"
echo "Created Node project: $name"
;;
bash)
mkdir -p "$name"
echo "# $name" > "$name/README.md"
printf '#!/usr/bin/env bash\nset -euo pipefail\n\necho "Hello from %s"\n' "$name" > "$name/main.sh"
chmod +x "$name/main.sh"
echo "Created Bash project: $name"
;;
web)
mkdir -p "$name/css" "$name/js"
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
Comment on lines +591 to +592
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 HTML escaping is now dead code

The <&lt; and >&gt; substitutions on these two lines can never trigger because the input validation on line 536 (^[a-zA-Z0-9_-]+$) already rejects any name containing <, >, or &. The escaped_name variable is identical to $name in every reachable code path, so the variable and both assignments can be removed:

Suggested change
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"

Removing the dead escaping also makes it immediately obvious that the name is safe to embed directly, thanks to the earlier validation guard.

Prompt To Fix With AI
This is a comment left during a code review.
Path: utility.sh
Line: 573-574

Comment:
**HTML escaping is now dead code**

The `<``&lt;` and `>``&gt;` substitutions on these two lines can never trigger because the input validation on line 536 (`^[a-zA-Z0-9_-]+$`) already rejects any name containing `<`, `>`, or `&`. The `escaped_name` variable is identical to `$name` in every reachable code path, so the variable and both assignments can be removed:

```suggestion
          echo "<!DOCTYPE html><html><head><title>$name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
```

Removing the dead escaping also makes it immediately obvious that the name is safe to embed directly, thanks to the earlier validation guard.

How can I resolve this? If you propose a fix, please make it concise.

echo "<!DOCTYPE html><html><head><title>$escaped_name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$escaped_name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
Comment on lines +591 to +593
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 & not escaped in HTML template (incomplete fix)

The previous fix added <&lt; and >&gt; escaping, but &&amp; is still missing. This means a project name like foo & bar will produce:

<title>foo & bar</title>
<h1>foo & bar</h1>

A bare & not followed by a valid entity reference is technically invalid HTML and can cause browsers to issue parse warnings. Additionally, the & substitution must happen first — if it were added after the current </> substitutions, the &lt; and &gt; sequences already written would get double-encoded into &amp;lt; / &amp;gt;.

Suggested change
local escaped_name="${name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
echo "<!DOCTYPE html><html><head><title>$escaped_name</title><link rel=\"stylesheet\" href=\"css/style.css\"></head><body><h1>$escaped_name</h1><script src=\"js/main.js\"></script></body></html>" > "$name/index.html"
local escaped_name="${name//&/&amp;}"
escaped_name="${escaped_name//</&lt;}"
escaped_name="${escaped_name//>/&gt;}"
Prompt To Fix With AI
This is a comment left during a code review.
Path: utility.sh
Line: 569-571

Comment:
**`&` not escaped in HTML template (incomplete fix)**

The previous fix added `<``&lt;` and `>``&gt;` escaping, but `&``&amp;` is still missing. This means a project name like `foo & bar` will produce:

```html
<title>foo & bar</title>
<h1>foo & bar</h1>
```

A bare `&` not followed by a valid entity reference is technically invalid HTML and can cause browsers to issue parse warnings. Additionally, the `&` substitution **must happen first** — if it were added after the current `<`/`>` substitutions, the `&lt;` and `&gt;` sequences already written would get double-encoded into `&amp;lt;` / `&amp;gt;`.

```suggestion
          local escaped_name="${name//&/&amp;}"
          escaped_name="${escaped_name//</&lt;}"
          escaped_name="${escaped_name//>/&gt;}"
```

How can I resolve this? If you propose a fix, please make it concise.

touch "$name/css/style.css" "$name/js/main.js"
echo "Created Web project: $name"
;;
*) echo "Unknown template: $tmpl. Available: python, node, bash, web" ; return 1 ;;
esac
;;

sequence)
if [[ "$1" != "with" || "$2" != "prefix" ]]; then
echo "Usage: u7 mk sequence with prefix <prefix> limit <N>"
Expand Down Expand Up @@ -557,6 +611,7 @@ Entities:
link <source> to <destination> Create symbolic link
archive <output> from <files...> Create archive from <files...> to <output>
clone <repo> [to <directory>] Git clone a repository
template <python|node|bash|web> <name> Scaffold a project structure
sequence with prefix <prefix> limit <N> Generate numbered sequence with prefix <prefix> and limit <N>
EOF
;;
Expand Down
Loading