{
  "name": "Highlight External Links",
  "description": "When a page opens, finds every off-site link and highlights it so you can see at a glance what leaves the site.",
  "tags": [
    "links",
    "highlight",
    "external",
    "browser",
    "audit",
    "security"
  ],
  "type": "triggered",
  "nodes": [
    {
      "id": "sticky-intro",
      "position": {
        "x": 20,
        "y": 20
      },
      "data": {
        "color": "#fff266",
        "content": "🚪 See which links leave the site.\n\nWhen a page opens, this collects its links, keeps the external http(s) ones, and highlights them right on the page for a few seconds. Handy for spotting sponsored or off-site links at a glance."
      },
      "type": "stickyNote",
      "width": 360,
      "height": 190
    },
    {
      "id": "trigger-page-load",
      "position": {
        "x": 120,
        "y": 300
      },
      "data": {
        "instance": {
          "id": "af-base-node:trigger:pageLoad"
        },
        "label": "When any page opens",
        "inputs": {
          "urlPatterns": [
            "<all_urls>"
          ]
        },
        "parameters": {
          "notes": "Runs on every page load."
        }
      },
      "type": "trigger"
    },
    {
      "id": "get-links",
      "position": {
        "x": 440,
        "y": 300
      },
      "data": {
        "instance": {
          "id": "af-base-node:basic:getAllLinksNode"
        },
        "label": "Read the page links",
        "inputs": {
          "outputFieldName": "links"
        },
        "parameters": {
          "notes": "Collects every link on the page."
        }
      },
      "type": "basic"
    },
    {
      "id": "build-selectors",
      "position": {
        "x": 760,
        "y": 300
      },
      "data": {
        "instance": {
          "id": "af-base-node:basic:code"
        },
        "label": "Pick external ones",
        "inputs": {
          "code": "links = input.get('links', []) if isinstance(input, dict) else (input or [])\nsels = []\nseen = set()\nfor l in links:\n    if not isinstance(l, str):\n        continue\n    if not (l.startswith('http://') or l.startswith('https://')):\n        continue\n    if '\"' in l or l in seen:\n        continue\n    seen.add(l)\n    sels.append('a[href=\"%s\"]' % l)\n{'selectors': sels[:200], 'count': len(sels)}"
        },
        "parameters": {
          "notes": "Python: keeps absolute http(s) links and turns each into a selector that matches its anchor on the page. The last line is the result."
        }
      },
      "type": "basic"
    },
    {
      "id": "highlight",
      "position": {
        "x": 1080,
        "y": 300
      },
      "data": {
        "instance": {
          "id": "af-base-node:basic:highlightElementsNode"
        },
        "label": "Highlight external links",
        "inputs": {
          "selectors": "{{ $input.result.selectors }}",
          "label": "external",
          "durationMs": 5000
        },
        "parameters": {
          "notes": "Highlights each external link on the page for a few seconds."
        }
      },
      "type": "basic"
    }
  ],
  "edges": [
    {
      "id": "e-load-get",
      "type": "flowEdge",
      "source": "trigger-page-load",
      "target": "get-links"
    },
    {
      "id": "e-get-build",
      "type": "flowEdge",
      "source": "get-links",
      "target": "build-selectors"
    },
    {
      "id": "e-build-hl",
      "type": "flowEdge",
      "source": "build-selectors",
      "target": "highlight"
    }
  ]
}