diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index b7a9408..7f5325d 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -6,12 +6,12 @@ on: branches: [ "main" ] paths: - '**' + - '.github/workflows/*.yml' - "!package.json" - '!.github/**' - '!*.yml' - '!*.config' - '!*.md' - - '.github/workflows/*.yml' workflow_dispatch: inputs: { } diff --git a/.github/workflows/pr_triage.yml b/.github/workflows/pr_triage.yml index f2d6166..0504ad7 100644 --- a/.github/workflows/pr_triage.yml +++ b/.github/workflows/pr_triage.yml @@ -35,12 +35,18 @@ jobs: if (!assignees.includes(assignee)) { if (assignee.includes('bot')) { - assignee = 'fsegurai'; + await github.rest.pulls.requestReviewers({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + reviewers: ['fsegurai'] + }); + } else { + await github.rest.issues.addAssignees({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + assignees: [assignee] + }); } - await github.rest.issues.addAssignees({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr.number, - assignees: [assignee] - }); } diff --git a/.github/workflows/release-demo.yml b/.github/workflows/release-demo.yml index e1d2e79..c9e7786 100644 --- a/.github/workflows/release-demo.yml +++ b/.github/workflows/release-demo.yml @@ -28,6 +28,9 @@ permissions: jobs: build: + if: | + github.ref == 'refs/heads/main' && + github.event.repository.fork == false runs-on: ubuntu-latest timeout-minutes: 2 environment: github-pages @@ -71,6 +74,9 @@ jobs: if-no-files-found: error release: + if: | + github.ref == 'refs/heads/main' && + github.event.repository.fork == false runs-on: ubuntu-latest timeout-minutes: 2 environment: github-pages diff --git a/.github/workflows/release-library.yml b/.github/workflows/release-library.yml index 8138367..a267f78 100644 --- a/.github/workflows/release-library.yml +++ b/.github/workflows/release-library.yml @@ -23,6 +23,9 @@ env: jobs: build: + if: | + github.ref == 'refs/heads/main' && + github.event.repository.fork == false runs-on: ubuntu-latest timeout-minutes: 2 environment: FSI_DEP_NodeJs @@ -62,6 +65,9 @@ jobs: if-no-files-found: error release: + if: | + github.ref == 'refs/heads/main' && + github.event.repository.fork == false needs: [ build ] runs-on: ubuntu-latest timeout-minutes: 2 diff --git a/demo/src/app/cheat-sheet/remote/links.md b/demo/src/app/cheat-sheet/remote/links.md index 29b58c6..fb96a5e 100644 --- a/demo/src/app/cheat-sheet/remote/links.md +++ b/demo/src/app/cheat-sheet/remote/links.md @@ -6,7 +6,7 @@ There are several ways to create links. [I'm a reference-style link][Arbitrary case-insensitive reference text] -[I'm a relative reference to a repository file](favicon.ico) +[I'm a relative reference to a repository file](/localFile:favicon.ico) [You can use numbers for reference-style link definitions][1] @@ -24,11 +24,13 @@ Some text to show that the reference links can follow later. [link text itself]: http://www.reddit.com -[I'm an Angular routerLink to another view with section](/routerLink:/syntax-highlight#language-pipe) +[Angular routerLink to another view with fragment](/routerLink:syntax-highlight#language-pipe) -[I'm an Angular routerLink to another view](/routerLink:/syntax-highlight) +[Angular routerLink to another view](/routerLink:syntax-highlight) -[I'm an Angular routerLink to a section on the same view](/routerLink:#headers) +[Angular routerLink with only fragment](#tables) + +[I'm an Angular routerLink to current view with fragment](/routerLink:cheat-sheet#tables) ```html n.includes('_ngcontent') || n.toLowerCase().includes('data-routerlink')) + element.getAttributeNames().some(n => angularAnchorAttributes.some(a => n.toLowerCase().includes(a))) ); } @@ -64,37 +72,45 @@ export class MarkdownLinkService { private internalUrlHandler(target: HTMLAnchorElement, routerLinkOptions?: MarkdownRouterLinkOptions): void { const anchor = target.nodeName.toLowerCase() === 'a' ? target : target.closest('a'); const path = anchor!.getAttribute('href')!; - - if (routerLinkOptions?.internalBrowserHandler) { - if (path.startsWith('#')) { - this._router.navigate([], { fragment: path.slice(1) }); - return; - } - - // Get the routerLink commands to navigate to - let commands = [anchor!.getAttribute('data-routerLink')!]; - + /** + * Handle the navigation based on the options provided + * @param commands - string - Path to navigate to using the router service + * @param fragment - string - Fragment to scroll to after navigation + */ + const handleNavigation = (commands: string, fragment?: string) => { let extras: NavigationExtras | undefined; - // Find the path in the routerLinkOptions + if (routerLinkOptions?.paths) { - extras = routerLinkOptions.paths[path]; + extras = routerLinkOptions.paths[commands]; } - // Get the global options if no path was found if (!extras && routerLinkOptions?.global) { extras = routerLinkOptions.global; } - // If the route has a fragment, add it to the extras and remove it from the commands to leave the path - if (path.includes('#')) { + if (fragment) { extras = extras || {}; - extras.fragment = path.split('#')[1]; - commands[0] = commands[0].split('#')[0]; + extras.fragment = fragment; + } + + this._router.navigate([commands], extras); + }; + + if (routerLinkOptions?.internalBrowserHandler) { + if (path.startsWith('#')) { + this._router.navigate([], { fragment: path.slice(1) }); + return; } - // Remove the first slash from the path - commands = commands.map(c => c.startsWith('/') ? c.slice(1) : c); + if (path.startsWith('/routerLink:')) { + const routerLinkPath = path.replace('/routerLink:', ''); + const [commands, fragment] = routerLinkPath.split('#'); + handleNavigation(commands, fragment); + return; + } - // Navigate to the path using the router service - this._router.navigate(commands, extras); + // Fallback for other internal URLs + const [commands, fragment] = path.split('#'); + handleNavigation(commands, fragment); + return; } else { try { // Validate if there are more than one element with the same id @@ -107,8 +123,6 @@ export class MarkdownLinkService { console.error(error); } } - - return; } /** diff --git a/lib/src/markdown.component.ts b/lib/src/markdown.component.ts index 67e4853..5c817cf 100644 --- a/lib/src/markdown.component.ts +++ b/lib/src/markdown.component.ts @@ -26,9 +26,9 @@ import { PrismPlugin } from './prism-plugin'; export interface MarkdownRouterLinkOptions { global?: NavigationExtras; paths?: Record; - internalBrowserHandler?: boolean; - internalDesktopHandler?: boolean; - externalBrowserHandler?: boolean; + internalBrowserHandler?: boolean; // Angular SPA navigation + internalDesktopHandler?: boolean; // Electron desktop navigation + externalBrowserHandler?: boolean; // External browser navigation } @Component({ @@ -174,8 +174,16 @@ export class MarkdownComponent implements OnChanges, AfterViewInit, OnDestroy { map(() => this.element.nativeElement.querySelectorAll('a')), switchMap(links => from(links)), filter(link => link.getAttribute('href')?.includes('/routerLink:') === true), - tap(link => link.setAttribute('data-routerLink', link.getAttribute('href')!.replace('/routerLink:', ''))), - tap(link => link.setAttribute('href', link.getAttribute('href')!.replace('/routerLink:', ''))), + tap(link => { + const href = link.getAttribute('href')!; + const [path, fragment] = href.split('#'); + link.setAttribute('data-routerLink', path); + link.setAttribute('href', `${path}${fragment ? `#${fragment}` : ''}`); + link.setAttribute('routerLink', `${path}${fragment ? `#${fragment}` : ''}`); + if (fragment) { + link.setAttribute('fragment', fragment); + } + }), ); @HostListener('click', ['$event']) diff --git a/package.json b/package.json index 82f52c6..d87ff7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@fsegurai/ngx-markdown", - "version": "18.1.0-beta.2", + "version": "18.1.0-beta.3", "description": "Angular library that uses marked to parse markdown to html combined with Prism.js for syntax highlights", "homepage": "https://github.com/fsegurai/ngx-markdown", "license": "MIT",