diff --git a/.github/workflows/agentscan.yml b/.github/workflows/agentscan.yml new file mode 100644 index 0000000..cf7eb35 --- /dev/null +++ b/.github/workflows/agentscan.yml @@ -0,0 +1,55 @@ +name: AgentScan + +on: + # Do NOT add actions/checkout to this workflow: pull_request_target runs + # with write permissions, so checking out PR code would allow a malicious + # PR to run arbitrary code with access to the token. + # Only `opened` (not `reopened`): a flagged PR/issue that gets reopened + # stays open for manual review, as the flag messages promise. + # To trigger a scan manually, add the `agentscan:scan` label to any PR + # or issue (remove and re-add it to re-scan). + pull_request_target: + types: + - opened + - labeled + issues: + types: + - opened + - labeled + +concurrency: + group: agentscan-${{ github.event.pull_request.number || github.event.issue.number }} + cancel-in-progress: true + +jobs: + agentscan: + # On `labeled` events, only run for the manual-trigger label (the scan + # itself adds `agentscan:*` labels, which must not re-trigger it). + if: github.event.action != 'labeled' || github.event.label.name == 'agentscan:scan' + runs-on: ubuntu-latest + permissions: + pull-requests: write + issues: write + contents: read + steps: + - name: AgentScan + uses: MatteoGabriele/agentscan-action@e02ef270c024bfad3541b2a71619c3c9f20b3312 # v2.2.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + scan-issues: true + auto-close: true + trusted-author-associations: '["owner", "member", "collaborator"]' + # Only `automation` and community-flagged accounts are auto-closed + # (the action's default); `mixed` is labeled and left open. + message-mixed: | + This was flagged as potentially not having a human behind it. + If this was flagged in error, we apologize. + A maintainer will review it manually. + message-automation: | + This was flagged as potentially not having a human behind it, and so it was closed. + If this was flagged in error, we apologize. + Please reopen it and we will manually review it. + message-community-flagged: | + This was flagged as potentially not having a human behind it, and so it was closed. + If this was flagged in error, we apologize. + Please reopen it and we will manually review it. diff --git a/README.md b/README.md index af10bf3..6a3de02 100644 --- a/README.md +++ b/README.md @@ -258,6 +258,26 @@ following features: containing block. To work around this, the polyfill strips any non-`auto` inset from the target (setting `inset: auto`) and re-applies it as padding on the wrapper, so the wrapper continues to drive positioning. + - Moving the target into the wrapper disconnects and reconnects it. If the + target is a custom element, its `connectedCallback` therefore runs more + than once, and any setup that can only happen once must be guarded — for + example, calling `attachShadow()` a second time throws. This applies to + any custom element the polyfill positions with `position-area`, including + a host positioned by a `position-area` in its own `:host` rule: + + ```js + class MyElement extends HTMLElement { + connectedCallback() { + if (this.shadowRoot) return; + this.attachShadow({ mode: 'open' }); + // ... + } + } + ``` + + Setting [`positionAreaContainingBlock`](#positionareacontainingblock) to + `false` (or `'auto'`, for targets that don't need the wrapper) avoids the + wrapper, and with it the reconnection. - When the wrapper is not added, styles that resolve against the containing block — percentage sizes, `auto` or percentage margins, percentage padding, or `stretch`/`anchor-center` self-alignment — will not match native diff --git a/position-area.html b/position-area.html index fcb1aba..d72e820 100644 --- a/position-area.html +++ b/position-area.html @@ -183,6 +183,29 @@

+
+

+ + span-left top, padding set inline ✅ +

+
+
Anchor
+
+ Target with longer content +
+
+

+ The same as the demo above, except that + padding-right: 50% is an inline style rather than a + stylesheet rule. Inline styles are shifted into custom properties like + the rest of the CSS, so auto mode can + still see the percentage padding and wraps the target. Without that + shift the padding reads back as empty, the target is positioned + directly, and the padding resolves against the original containing block + instead of the position-area cell. +

+
+

diff --git a/public/position-area-page.css b/public/position-area-page.css index 2f282f9..a676ab6 100644 --- a/public/position-area-page.css +++ b/public/position-area-page.css @@ -67,6 +67,12 @@ position-area: span-left top; } +/* Same as `.spanleft-top`, but the containing-block-dependent padding is set + * as an inline style on the target instead. */ +.target.inline-shifted { + position-area: span-left top; +} + .target.spanall-left { position-area: span-all left; } diff --git a/shadow-dom.html b/shadow-dom.html index b835fb9..933e046 100644 --- a/shadow-dom.html +++ b/shadow-dom.html @@ -27,6 +27,12 @@ anchor-adopted-styles { width: 100%; } + + registry-anchor, + scoped-registry-host { + display: block; + flex: 1; + }