Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ nautilus | serika
* [x] Add Skills: Software & IDEs widget
* [ ] Make autobuilder instead of manual build and push
* [ ] Count organization repositories (+ their stars)
* [ ] Truncate name if too long on profile widget
* [x] Truncate name if too long on profile widget
* [ ] Make all widgets a modular size
* [ ] Add Profile Tag widget
* [ ] Add Skill Tag widget
Expand Down
47 changes: 34 additions & 13 deletions public/src/widgets/profile.js

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

2 changes: 1 addition & 1 deletion public/src/widgets/profile.js.map

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

41 changes: 35 additions & 6 deletions src/widgets/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,31 @@ export default async function profileWidget(
const width = 842
const height = 165

// Escapes characters that would otherwise break the SVG's XML structure.
function escapeXml(value: string): string {
return value
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
}

// Truncates the display name so it never runs into the data boxes on the right,
// which shift further left the more data options are requested.
function truncateName(name: string): string {
const CHAR_WIDTH = 13
const NAME_START_X = 145
const NAME_RIGHT_MARGIN = 20
const dataBoxesWidth = dataOptions.length * 108
const availableWidth =
width - 52 - dataBoxesWidth - NAME_START_X - NAME_RIGHT_MARGIN
const maxChars = Math.max(1, Math.floor(availableWidth / CHAR_WIDTH))

if (name.length <= maxChars) {
return name
}
return name.slice(0, Math.max(1, maxChars - 1)) + '…'
}

async function getDataOptions(): Promise<string> {
let dataBoxes = ''

Expand Down Expand Up @@ -187,12 +212,16 @@ export default async function profileWidget(
${buildCard(width, height, theme.background)}
<g id="profile-card">
<rect id="profile-image" width="65" height="65" rx="30" transform="translate(52 47)" fill="url(#pattern)"/>
<text id="text-name" fill="${theme.title}" data-name="text-name" transform="translate(145 78)" font-size="26" font-family="Roboto-Medium, Roboto, sans-serif" font-weight="500"><tspan x="0" y="0">${response.data.name === null
? response.data.login
: response.data.name
}</tspan></text>
<text id="text-url" data-name="text-url" transform="translate(145 102)" fill="#bfbfbf" font-size="16" font-family="Roboto-Regular, Roboto, sans-serif"><tspan x="0" y="0">GitHub.com/${response.data.login
}</tspan></text>
<text id="text-name" fill="${theme.title}" data-name="text-name" transform="translate(145 78)" font-size="26" font-family="Roboto-Medium, Roboto, sans-serif" font-weight="500"><tspan x="0" y="0">${escapeXml(
truncateName(
response.data.name === null
? response.data.login
: response.data.name
)
)}</tspan></text>
<text id="text-url" data-name="text-url" transform="translate(145 102)" fill="#bfbfbf" font-size="16" font-family="Roboto-Regular, Roboto, sans-serif"><tspan x="0" y="0">GitHub.com/${escapeXml(
response.data.login
)}</tspan></text>
<g id="data-boxes" transform="translate(${width - 52
} ${(height - 37) / 2})">
${dataBoxes}
Expand Down