diff --git a/packages/ia-topnav/README.md b/packages/ia-topnav/README.md index a5e9a87b3..b4838d03b 100644 --- a/packages/ia-topnav/README.md +++ b/packages/ia-topnav/README.md @@ -4,6 +4,7 @@ https://git.archive.org/www/offshoot/-/blob/main/guides/update-top-nav.md ## Installation +## Add to your project ```bash yarn add @internetarchive/ia-topnav ``` diff --git a/packages/ia-topnav/package.json b/packages/ia-topnav/package.json index 206bada2b..8385f4f8b 100644 --- a/packages/ia-topnav/package.json +++ b/packages/ia-topnav/package.json @@ -1,6 +1,6 @@ { "name": "@internetarchive/ia-topnav", - "version": "1.1.29", + "version": "1.1.30-alpha.2", "description": "Top nav for Internet Archive", "license": "AGPL-3.0-only", "main": "index.js", diff --git a/packages/ia-topnav/src/ia-topnav.js b/packages/ia-topnav/src/ia-topnav.js index a8a19e63f..322c60ad3 100644 --- a/packages/ia-topnav/src/ia-topnav.js +++ b/packages/ia-topnav/src/ia-topnav.js @@ -89,7 +89,7 @@ export default class IATopNav extends LitElement { menuSetup() { this.localLinks = this.getAttribute('localLinks') !== 'false' && this.getAttribute('localLinks') !== false; this.username = this.getAttribute('username') - this.screenName = this.username; // set screenName when username changes to display + this.screenName = this.getAttribute('screenName') // this.username; // set screenName when username changes to display this.waybackPagesArchived = this.getAttribute('waybackPagesArchived') ?? '' // ensure we update other components that use `baseHost` diff --git a/packages/ia-topnav/src/primary-nav.js b/packages/ia-topnav/src/primary-nav.js index c33349f05..ec6acfd38 100644 --- a/packages/ia-topnav/src/primary-nav.js +++ b/packages/ia-topnav/src/primary-nav.js @@ -79,9 +79,24 @@ class PrimaryNav extends TrackedElement { ); } + get isRTL() { + // https://stackoverflow.com/questions/12006095/javascript-how-to-check-if-character-is-rtl + const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF'; + const rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'; + const rtlCheck = new RegExp('^[^'+ltrChars+']*['+rtlChars+']'); + + return rtlCheck.test(this.screenName); + } + get truncatedScreenName() { - if (this.screenName && this.screenName.length > 10) { - return `${this.screenName.substr(0, 9)}…`; + if (this.screenName && [...this.screenName].length > 10) { + // Works with RTL and Unicode + const truncated = [...this.screenName].slice(0, 9).join(''); + if (this.isRTL) { + return `…${truncated}`; + } else { + return `${truncated}…`; + } } return this.screenName; } diff --git a/packages/ia-topnav/test/primary-nav.test.js b/packages/ia-topnav/test/primary-nav.test.js index c4544a0d0..e341a1f54 100644 --- a/packages/ia-topnav/test/primary-nav.test.js +++ b/packages/ia-topnav/test/primary-nav.test.js @@ -56,6 +56,30 @@ describe('', () => { expect(usernameSpan.innerText).to.equal('somesuper…'); }); + it('truncates a long screen name with extended characters', async () => { + const el = await fixture(component({ + baseHost: 'archive.org', + username: '@foo', + screenName: 'a😊b😊c😊d😊😊😊😊😊😊😊😊', + })); + + const usernameSpan = el.shadowRoot.querySelector('.username'); + + expect(usernameSpan.innerText).to.equal('a😊b😊c😊dπŸ˜ŠπŸ˜Šβ€¦'); + }); + + it('truncates a long screen name with RTL extended characters', async () => { + const el = await fixture(component({ + baseHost: 'archive.org', + username: '@foo', + screenName: ' Ψ§Ω„Ψ―ΩƒΨͺور Ω…Ψ­Ω…Ψ§Ω„Ψ―ΩƒΨͺور Ω…Ψ­Ω…Ψ― Ψ§Ω„ΨΉΨ¬ΩˆΨ²', + })); + + const usernameSpan = el.shadowRoot.querySelector('.username'); + + expect(usernameSpan.innerText).to.equal('… Ψ§Ω„Ψ―ΩƒΨͺور '); + }); + it('opens a slot with `secondIdentitySlotMode`', async () => { const el = await fixture(component({ baseHost: 'archive.org', diff --git a/www/ia-topnav/index.html b/www/ia-topnav/index.html index 67c0db150..bedbcb738 100644 --- a/www/ia-topnav/index.html +++ b/www/ia-topnav/index.html @@ -17,10 +17,14 @@

demo

-
+ +