Skip to content

Commit

Permalink
Use encodeURIComponent to avoid image collisions when non-alphanumeri…
Browse files Browse the repository at this point in the history
…c characters are used
  • Loading branch information
Alan19 committed Jul 30, 2024
1 parent a4a93c2 commit 9df8053
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .idea/jsonSchemas.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 0 additions & 79 deletions api/routes/imageSchema.json

This file was deleted.

102 changes: 102 additions & 0 deletions api/routes/image_list_schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"title": "Image",
"description": "An image for my personal website's filterable gallery",
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"required": [
"href",
"artist",
"tags",
"title"
],
"properties": {
"src": {
"description": "The source URL for the image",
"type": "string"
},
"href": {
"description": "The link to direct the viewer to upon clicking the image",
"type": "string"
},
"thumbnailUrl": {
"description": "The link to the smaller version of the image to display on the gallery",
"type": "string"
},
"title": {
"description": "A title for the image for display on the gallery",
"type": "string"
},
"artist": {
"description": "The social media handle of the artist, usually prefixed with an @, displayed on the gallery",
"type": "string"
},
"artistURL": {
"description": "A link to the artist's social media page",
"type": "string"
},
"published": {
"description": "The date when the artwork was published",
"type": "string",
"format": "date"
},
"webp": {
"description": "A link to the webp version of the image, used by image display modal if available",
"type": "string"
},
"tags": {
"description": "An array of tags for the art",
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string"
}
}
}
},
{
"type": "object",
"required": [
"parent",
"href",
"tags",
"src"
],
"properties": {
"src": {
"description": "The source URL for the image",
"type": "string"
},
"href": {
"description": "The link to direct the viewer to upon clicking the image",
"type": "string"
},
"thumbnailUrl": {
"description": "The link to the smaller version of the image to display on the gallery",
"type": "string"
},
"parent": {
"description": "The name of the parent image that this image is an alt for",
"type": "string"
},
"webp": {
"description": "A link to the webp version of the image, used by image display modal if available",
"type": "string"
},
"tags": {
"description": "An array of tags for the art",
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string"
}
}
}
}
]
}
}
24 changes: 24 additions & 0 deletions api/routes/images.json
Original file line number Diff line number Diff line change
Expand Up @@ -3408,5 +3408,29 @@
"src": "https://alcorsiteartbucket.s3.amazonaws.com/alts/Soma%20Hardlight%20Armor_1.png",
"thumbnailUrl": "https://alcorsiteartbucket.s3.amazonaws.com/thumbnail/alts/soma_hardlight_armor_1.webp",
"webp": "https://alcorsiteartbucket.s3.amazonaws.com/webp/alts/soma_hardlight_armor_1.webp"
},
{
"title": "Hanfu Sketch",
"artist": "@KuroPenguinEx",
"tags": [
"Rastaban Form"
],
"href": "https://x.com/FaintAlcor/status/1818149053839941913",
"published": "2024-07-30",
"aspectRatio": 0.7069555302166477,
"src": "https://alcorsiteartbucket.s3.amazonaws.com/hanfu_sketch.png",
"thumbnailUrl": "https://alcorsiteartbucket.s3.amazonaws.com/thumbnail/hanfu_sketch.webp",
"webp": "https://alcorsiteartbucket.s3.amazonaws.com/webp/hanfu_sketch.webp"
},
{
"tags": [
""
],
"href": "",
"aspectRatio": 0.7069555302166477,
"parent": "Hanfu Sketch",
"src": "https://alcorsiteartbucket.s3.amazonaws.com/alts/Hanfu%20Sketch_1.png",
"thumbnailUrl": "https://alcorsiteartbucket.s3.amazonaws.com/thumbnail/alts/hanfu_sketch_1.webp",
"webp": "https://alcorsiteartbucket.s3.amazonaws.com/webp/alts/hanfu_sketch_1.webp"
}
]
35 changes: 2 additions & 33 deletions api/routes/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const sharp = require('sharp')
const path = require('path')
dotenv.config();
router.use(express.json());
const _ = require("lodash");

// Configure AWS SDK
AWS.config.update({
Expand All @@ -20,40 +21,8 @@ const s3 = new AWS.S3();
const storage = multer.memoryStorage();
const upload = multer({storage});

function convertToSnakeCase(str) {
return str && str.match(
/[A-Z]{2,}(?=[A-Z][a-z]+[0-9]*|\b)|[A-Z]?[a-z]+[0-9]*|[A-Z]|[0-9]+/g)
.map(s => s.toLowerCase())
.join('_');
}

function convertGreekToUnicode(str) {
const greekToUnicodeMap = {
'Α': 'U+0391', 'Β': 'U+0392', 'Γ': 'U+0393', 'Δ': 'U+0394', 'Ε': 'U+0395',
'Ζ': 'U+0396', 'Η': 'U+0397', 'Θ': 'U+0398', 'Ι': 'U+0399', 'Κ': 'U+039A',
'Λ': 'U+039B', 'Μ': 'U+039C', 'Ν': 'U+039D', 'Ξ': 'U+039E', 'Ο': 'U+039F',
'Π': 'U+03A0', 'Ρ': 'U+03A1', 'Σ': 'U+03A3', 'Τ': 'U+03A4', 'Υ': 'U+03A5',
'Φ': 'U+03A6', 'Χ': 'U+03A7', 'Ψ': 'U+03A8', 'Ω': 'U+03A9',
'α': 'U+03B1', 'β': 'U+03B2', 'γ': 'U+03B3', 'δ': 'U+03B4', 'ε': 'U+03B5',
'ζ': 'U+03B6', 'η': 'U+03B7', 'θ': 'U+03B8', 'ι': 'U+03B9', 'κ': 'U+03BA',
'λ': 'U+03BB', 'μ': 'U+03BC', 'ν': 'U+03BD', 'ξ': 'U+03BE', 'ο': 'U+03BF',
'π': 'U+03C0', 'ρ': 'U+03C1', 'σ': 'U+03C3', 'τ': 'U+03C4', 'υ': 'U+03C5',
'φ': 'U+03C6', 'χ': 'U+03C7', 'ψ': 'U+03C8', 'ω': 'U+03C9'
};

let result = '';
for (let char of str) {
if (greekToUnicodeMap[char]) {
result += greekToUnicodeMap[char];
} else {
result += char;
}
}
return result;
}

function prepareFileName(title) {
return convertToSnakeCase(convertGreekToUnicode(title));
return encodeURIComponent(_.snakeCase(title));
}

router.post('/', upload.single('image'), async (req, res) => {
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@
"@testing-library/react": "^14.3.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.7",
"@types/node": "^20.14.9",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"aws-sdk": "^2.1651.0",
"axios": "^1.7.2",
"dayjs": "^1.11.11",
"lodash": "^4.17.21",
"lz-string": "^1.5.0",
"react": "^18.3.1",
"react-clipboard.js": "^2.0.16",
Expand Down
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/components/SkeletonImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const SkeletonImage = memo(function SkeletonImage(props: {
}, [src]);

if (isReady) {
const img = <img alt={alt} loading={"lazy"} className={imageClassname} onClick={onClick} style={{...style}} src={src}/>;
const img = <img alt={alt} loading={"lazy"} className={imageClassname} onClick={onClick} style={{display: 'block', ...style}} src={src}/>;
return <>
{
props.hasAlts &&
Expand Down
11 changes: 8 additions & 3 deletions src/components/about/characters/SomaInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ export function SomaInfo() {
</Grid>
<AboutPageParagraph
text={"Soma is a character for a custom class-less TTRPG ruleset, but his aesthetic is most similar to that of a bard and a swashbuckler. At a young age, an accident caused his brain to upgraded to an artificial brain constructed from exotic materials from another world. Because of his brain replacement, his parents moved him from a traditional fantasy city to a space age rural community, where they are more equipped to handle his new condition if necessary. His upgraded brain allows him to better manage his mental state and also allows him to hack devices remotely. Shortly after his 19th birthday, while he was on a shopping trip in his old hometown, he got swept up in the initiation trials for the newly reopened Adventurer's Society. He passed, allowing him to be initiated as an adventurer, and then proceeded to set off with some others who took the trial with him on a journey to resolve festering complications in his homeland and beyond."}
title={'Synopsis'} img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/soma_v3.webp'} />
<AboutPageParagraph text={"Soma's primary weapon is a professionally made dueling sword. He also has a dart pistol loaded with various elemental and debilitating ammo that can help with crowd control and debuffing enemies. In more deadly situations, he also has a nano blade that can inflict heavy damage to highly durable enemies. He also has a suit of armor made out of hardlight that can suddenly materialize around his body, which is reminiscent of an anime transformation sequence."} title={'Fighting Style'} img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/soma_hardlight_armor.webp'} />
<AboutPageParagraph title={'Elemental Growth'} text={"Soma is from a universe where people have a mishmash of elemental traits on their bodies at get stronger with practice. Before the adventure started, he looked more human, without a wooden horn protruding out of his forehead and one of his eyes was not replaced with a flower. His hair also didn't glow, and he doesn't have the ability to float."} img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/seasoned_adventurer_outfit.webp'} />
title={'Synopsis'} img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/soma_v3.webp'}/>
<AboutPageParagraph
text={"Soma's primary weapon is a professionally made dueling sword. He also has a dart pistol loaded with various elemental and debilitating ammo that can help with crowd control and debuffing enemies. In more deadly situations, he also has a nano blade that can inflict heavy damage to highly durable enemies. He also has a suit of armor made out of hardlight that can suddenly materialize around his body, which is reminiscent of an anime transformation sequence."}
title={'Fighting Style'} img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/soma_hardlight_armor.webp'}/>
<AboutPageParagraph
text={"Before his journey began, Soma looked almost entirely human, lacking the wooden horn on his forehead, the flower in place of one eye, and the glowing hair. He couldn't float as if suspended in water. In his universe, elemental traits grow stronger with practice, and it took many trials for Soma's physical traits to transcend ordinary human physiology."}
title={'Elemental Growth'}
img={'https://alcorsiteartbucket.s3.amazonaws.com/webp/seasoned_adventurer_outfit.webp'}/>
</Grid>
</Fade>

Expand Down
6 changes: 3 additions & 3 deletions src/components/gallery/Gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import {FilterPane} from "./FilterPane";
import {RouteWithSubpanel} from "../navigation/RouteWithSubpanel";
import {SkeletonImage} from "../SkeletonImage";
import {TSJustifiedLayout} from "react-justified-layout-ts";
import {createSearchParams, useLocation, useNavigate} from "react-router-dom";
import {convertToSnakeCase} from "./image/ArtworkPage";
import {createSearchParams, useNavigate} from "react-router-dom";
import {useQueryState} from "react-router-use-location-state";
import {prepareFileName} from "./Utils";

export function getMonthYearPairsInImageSet(images: ImageInformation[]): Set<string> {
// @ts-ignore
Expand Down Expand Up @@ -93,7 +93,7 @@ export const Gallery = memo(function Gallery() {
navigation({
pathname: "/artwork",
search: createSearchParams({
title: convertToSnakeCase(value.title)
title: prepareFileName(value.title)
}).toString()
})
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/gallery/Utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {snakeCase} from "lodash";

export function prepareFileName(title: string) {
return encodeURIComponent(snakeCase(title));
}
Loading

0 comments on commit 9df8053

Please sign in to comment.