Conversation
A Contribution for URL shortcut, now, Abbreviation .html directs to the exact page!
jmanico
left a comment
There was a problem hiding this comment.
I am approving just to move this along but can other folks take a closer look at this before we merge?
|
This is fantastic. I'm going to do a full review on it hopefully in the next day or two but I'm really excited about this. Thank you! |
|
This is fantastic - thank you very very much! |
|
Build is failing here @Farreeda |
scripts/Generate_Site_mkDocs.sh
Outdated
| echo " - /${shortcut}.html" | ||
| else | ||
| #echo "❌ Failed to create shortcuts for ${shortcut}" | ||
| fi |
There was a problem hiding this comment.
The script fails here, I assume because there's nothing in the else clause except for the comment. Uncommenting the line fixes this.
However, when I run this locally and run make serve the shortcuts don't seem to work. I also don't see where the script reads redirects.yml - it looks like the script is automatically generating the shortcuts which makes me wonder how it will handle possible duplicates. Can you please clarify the process?
There was a problem hiding this comment.
Thank you for your feedback, @szh! I appreciate your insights and apologize for not testing every case @mackowski. The redirects.yml file now includes abbreviations for each path, and it can be easily modified and updated as needed. The XSS and auth issues should be resolved now, but please note that abbreviations should be followed by .html
Thank you, @jmanico, for bringing attention to my PR!
|
@szh can you review it again? |
|
Sorry for the delay, I've been busy. I'll try to review it this week. |
|
I'm ready to approve. Just one question - I see it generates both the clean urls like |
|
The issue happens because the shortcut files (without .html) are being treated as raw files instead of actual HTML pages when accessed in a browser. The browser doesn't know how to interpret them, so it downloads them instead of rendering.
The issue happens because the shortcut files (without .html) are being treated as raw files instead of actual HTML pages when accessed in a browser. The browser doesn't know how to interpret them, so it downloads them instead of rendering. |
|
OK, so maybe we should just not create them? Or maybe there's some kind of config file (like a .htaccess file) that can instruct the server to serve them as html? |
|
Thank you for re-checking my PR @mackowski. |
I'd prefer to fix it before we merge :) |
|
ping |
|
Hello. After a year. |
|
Website build failed. not sure what to approve here. |
|
There was a problem hiding this comment.
Pull request overview
Adds a shortlink/redirect mechanism intended to let users reach common cheat sheets via memorable shortcut paths, supporting the goal in issue #1300.
Changes:
- Introduces a
scripts/redirects.ymlmapping of short names to target cheat sheet URLs. - Updates
scripts/Generate_Site_mkDocs.shto add page titles and generate redirect pages during site build. - Updates
Index.mdcheat sheet count and adds several cheat sheets to the alphabetical index.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| scripts/redirects.yml | Defines shortcut-to-target mappings used to generate redirect pages. |
| scripts/Generate_Site_mkDocs.sh | Adds helper functions and a redirect-generation step to the MkDocs build script. |
| Index.md | Updates the cheat sheet index count and entries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| check_dependencies() { | ||
| local deps=("mkdocs" "mkdocs-material" "pymdown-extensions") | ||
| python -c "import ${dep//-/_}" 2>/dev/null || { | ||
| echo "Missing dependency: $dep" | ||
| echo "Install with: pip install mkdocs mkdocs-material pymdown-extensions" | ||
| exit 1 | ||
| } | ||
| done | ||
| } |
| if [[ "$OSTYPE" == "darwin"* ]]; then | ||
| # MacOS | ||
| sed -i '' "1i\\ | ||
| Title: Introduction\\ | ||
| " "$WORK/cheatsheets/index.md" | ||
| sed -i '' 's/Index.md/Glossary.md/g' "$WORK/cheatsheets/Glossary.md" | ||
| sed -i '' "1i\\ | ||
| Title: Index Alphabetical\\ | ||
| " "$WORK/cheatsheets/Glossary.md" | ||
| sed -i '' "1i\\ | ||
| Title: Index ASVS\\ | ||
| " "$WORK/cheatsheets/IndexASVS.md" | ||
| sed -i '' "1i\\ | ||
| Title: Index MASVS\\ | ||
| " "$WORK/cheatsheets/IndexMASVS.md" | ||
| sed -i '' "1i\\ | ||
| Title: Index Proactive Controls\\ | ||
| " "$WORK/cheatsheets/IndexProactiveControls.md" | ||
| sed -i '' "1i\\ | ||
| Title: Index Top 10\\ | ||
| " "$WORK/cheatsheets/IndexTopTen.md" | ||
| sed -i '' 's/Index.md/Glossary.md/g' "$CHEATSHEETS_DIR/Glossary.md" | ||
| else | ||
| sed -i "1iTitle: Introduction\n" $WORK/cheatsheets/index.md | ||
| sed -i 's/Index.md/Glossary.md/g' $WORK/cheatsheets/Glossary.md | ||
| sed -i "1iTitle: Index Alphabetical\n" $WORK/cheatsheets/Glossary.md | ||
| sed -i "1iTitle: Index ASVS\n" $WORK/cheatsheets/IndexASVS.md | ||
| sed -i "1iTitle: Index MASVS\n" $WORK/cheatsheets/IndexMASVS.md | ||
| sed -i "1iTitle: Index Proactive Controls\n" $WORK/cheatsheets/IndexProactiveControls.md | ||
| sed -i "1iTitle: Index Top 10\n" $WORK/cheatsheets/IndexTopTen.md | ||
| sed -i 's/Index.md/Glossary.md/g' "$CHEATSHEETS_DIR/Glossary.md" | ||
| fi |
| cat > "$SITE_DIR/.htaccess" << 'EOF' | ||
| RewriteEngine On | ||
| RewriteCond %{REQUEST_FILENAME} !-f | ||
| RewriteCond %{REQUEST_FILENAME}.html -f | ||
| RewriteRule ^(.*)$ $1.html [L] | ||
| EOF | ||
|
|
||
| echo "Step 5/7: Generating URL shortcuts..." | ||
| if [ -f "../scripts/redirects.yml" ]; then | ||
| python3 << PYTHON_SCRIPT | ||
| import yaml | ||
| import os | ||
| import shutil | ||
|
|
||
| site_dir = "$SITE_DIR" | ||
|
|
||
| def create_redirect(shortcut, target, site_dir): | ||
| # Create a directory for the shortcut to allow /shortcut/ access | ||
| target_path = os.path.join(site_dir, shortcut) | ||
|
|
||
| # If a file exists with the shortcut name, remove it to avoid conflicts | ||
| if os.path.isfile(target_path): | ||
| os.remove(target_path) | ||
|
|
||
| os.makedirs(target_path, exist_ok=True) | ||
|
|
||
| # The 'index.html' inside the folder makes the clean URL work | ||
| output_file = os.path.join(target_path, "index.html") | ||
| target_url = target if target.startswith('http') else f'/{target}' | ||
|
|
||
| html = f"""<!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta http-equiv="refresh" content="0; url={target_url}"> | ||
| <link rel="canonical" href="{target_url}"> | ||
| <script>window.location.href = "{target_url}";</script> |
| cd "$WORK" || exit 1 | ||
|
|
||
| cd $WORK || exit | ||
| python -m mkdocs build --verbose || { | ||
| echo "ERROR: MkDocs build failed!" | ||
| exit 1 | ||
| } | ||
|
|
||
| if ! python -m mkdocs build; then | ||
| echo "Error detected during the generation of the site, generation failed!" | ||
| if [ ! -d "$SITE_DIR" ]; then | ||
| echo "ERROR: Site directory was not created!" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Step 6/7: Handling redirect for files that have changed" | ||
| #Authorization_Testing_Automation.md -> Authorization_Testing_Automation_Cheat_Sheet.md | ||
| #Drone_security_sheet.html -> Drone_Security_Cheat_Sheet.html | ||
| #Injection_Prevention_Cheat_Sheet_in_Java.md -> Injection_Prevention_in_Java_Cheat_Sheet.md | ||
| #JSON_WEB_Token_Cheat_Sheet_for_Java.md -> JSON_WEB_Token_for_Java_Cheat_Sheet.md | ||
| #Ruby_on_Rails_Cheatsheet.md -> Ruby_on_Rails_Cheat_Sheet.md | ||
| #Nodejs_security_cheat_sheet.html -> Nodejs_security_Cheat_Sheet.html | ||
|
|
||
| if [[ "$OSTYPE" == "darwin"* ]]; then | ||
| # MacOS | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Authorization_Testing_Automation.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Authorization_Testing_Automation_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Drone_security_sheet.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Drone_Security_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Injection_Prevention_Cheat_Sheet_in_Java.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Injection_Prevention_in_Java_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/JSON_Web_Token_Cheat_Sheet_for_Java.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/JSON_Web_Token_for_Java_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Ruby_on_Rails_Cheatsheet.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Ruby_on_Rails_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Nodejs_security_cheat_sheet.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Nodejs_Security_Cheat_Sheet.html" | ||
| sed -i '' "1i\\ | ||
| ---\\ | ||
| redirect_from: \"/cheatsheets/Application_Logging_Vocabulary_Cheat_Sheet.html\"\\ | ||
| ---\\ | ||
| " "$WORK/$GENERATED_SITE/cheatsheets/Logging_Vocabulary_Cheat_Sheet.html" | ||
| echo "Site built successfully" | ||
|
|
||
| cat > "$SITE_DIR/.htaccess" << 'EOF' | ||
| RewriteEngine On | ||
| RewriteCond %{REQUEST_FILENAME} !-f | ||
| RewriteCond %{REQUEST_FILENAME}.html -f | ||
| RewriteRule ^(.*)$ $1.html [L] | ||
| EOF | ||
|
|
||
| echo "Step 5/7: Generating URL shortcuts..." | ||
| if [ -f "../scripts/redirects.yml" ]; then | ||
| python3 << PYTHON_SCRIPT | ||
| import yaml | ||
| import os | ||
| import shutil | ||
|
|
||
| site_dir = "$SITE_DIR" |
| # Create redirect HTML page | ||
| create_redirect() { | ||
| local shortcut=$1 | ||
| local target=$2 | ||
| local output_file="$SITE_DIR/${shortcut}.html" | ||
|
|
||
| cat > "$output_file" << EOF | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <meta http-equiv="refresh" content="0; url=/${target}"> | ||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
| <script>window.location.href = "/${target}";</script> | ||
| </head> | ||
| <body> | ||
| Redirecting to <a href="/${target}">${target}</a>... | ||
| </body> | ||
| </html> | ||
| EOF | ||
| } | ||
|
|
||
| echo "Generate a offline portable website with all the cheat sheets..." | ||
|
|
||
| echo "Step 1/7: Init work folder." | ||
| mkdir -p "$CHEATSHEETS_DIR"/{cheatsheets,assets} |
| cheatsheets/Nodejs_security_cheat_sheet: cheatsheets/Nodejs_Security_Cheat_Sheet.html | ||
| cheatsheets/Application_Logging_Vocabulary_Cheat_Sheet: cheatsheets/Logging_Vocabulary_Cheat_Sheet.html | ||
|
|
||
| # Add more redirects as needed No newline at end of file |
Add URL Shortening for Cheat Sheets
Description
This PR adds automatic URL shortening functionality to make cheat sheets more accessible through memorable shortcuts. Instead of typing long URLs, users can now access cheat sheets using abbreviated paths.
For example:
/XSS.html→cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html/SSRF.html→cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html/SQLi.html→cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.htmlChanges
Generate_Site_mkDocs.sh/XSS.html)Testing
After running
Test shortcuts:
Benefits
Related Issues
Closes #1300