A CLI for publishing standard.site documents to ATProto sequoia.pub
standard site lexicon cli publishing
57
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add hide attribute to sequoia-comments component

Resolves #1

authored by

Heath Stewart and committed by tangled.org 9ef18c3f 08e41d32

+114 -124
+1 -14
bun.lock
··· 24 24 }, 25 25 "packages/cli": { 26 26 "name": "sequoia-cli", 27 - "version": "0.3.2", 27 + "version": "0.4.0", 28 28 "bin": { 29 29 "sequoia": "dist/index.js", 30 30 }, ··· 41 41 "devDependencies": { 42 42 "@biomejs/biome": "^2.3.13", 43 43 "@types/mime-types": "^3.0.1", 44 - "@types/node": "^20", 45 - }, 46 - "peerDependencies": { 47 - "typescript": "^5", 48 - }, 49 - }, 50 - "packages/ui": { 51 - "name": "sequoia-ui", 52 - "version": "0.1.0", 53 - "devDependencies": { 54 - "@biomejs/biome": "^2.3.13", 55 44 "@types/node": "^20", 56 45 }, 57 46 "peerDependencies": { ··· 1369 1358 "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], 1370 1359 1371 1360 "sequoia-cli": ["sequoia-cli@workspace:packages/cli"], 1372 - 1373 - "sequoia-ui": ["sequoia-ui@workspace:packages/ui"], 1374 1361 1375 1362 "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], 1376 1363
+1
docs/docs/pages/comments.mdx
··· 143 143 |-----------|------|---------|-------------| 144 144 | `document-uri` | `string` | - | AT Protocol URI for the document. Optional if a `<link rel="site.standard.document">` tag exists in the page head. | 145 145 | `depth` | `number` | `6` | Maximum depth of nested replies to fetch. | 146 + | `hide` | `string` | - | Set to "auto" to hide if no document link is detected | 146 147 147 148 ```html 148 149 <!-- Use attributes for explicit control -->
+56 -55
docs/docs/public/sequoia-comments.js
··· 14 14 * Attributes: 15 15 * - document-uri: AT Protocol URI for the document (optional if link tag exists) 16 16 * - depth: Maximum depth of nested replies to fetch (default: 6) 17 + * - hide: Set to "auto" to hide if no document link is detected 17 18 * 18 19 * CSS Custom Properties: 19 20 * - --sequoia-fg-color: Text color (default: #1f2937) ··· 573 574 class SequoiaComments extends BaseElement { 574 575 constructor() { 575 576 super(); 576 - this.shadow = this.attachShadow({ mode: "open" }); 577 + const shadow = this.attachShadow({ mode: "open" }); 578 + 579 + const styleTag = document.createElement("style"); 580 + shadow.appendChild(styleTag); 581 + styleTag.innerText = styles; 582 + 583 + const container = document.createElement("div"); 584 + shadow.appendChild(container); 585 + container.className = "sequoia-comments-container"; 586 + container.part = "container"; 587 + 588 + this.commentsContainer = container; 577 589 this.state = { type: "loading" }; 578 590 this.abortController = null; 591 + 579 592 } 580 593 581 594 static get observedAttributes() { 582 - return ["document-uri", "depth"]; 595 + return ["document-uri", "depth", "hide"]; 583 596 } 584 597 585 598 connectedCallback() { ··· 614 627 get depth() { 615 628 const depthAttr = this.getAttribute("depth"); 616 629 return depthAttr ? parseInt(depthAttr, 10) : 6; 630 + } 631 + 632 + get hide() { 633 + const hideAttr = this.getAttribute("hide"); 634 + return hideAttr === "auto"; 617 635 } 618 636 619 637 async loadComments() { ··· 666 684 } 667 685 668 686 render() { 669 - const styleTag = `<style>${styles}</style>`; 670 - 671 687 switch (this.state.type) { 672 688 case "loading": 673 - this.shadow.innerHTML = ` 674 - ${styleTag} 675 - <div class="sequoia-comments-container"> 676 - <div class="sequoia-loading"> 677 - <span class="sequoia-loading-spinner"></span> 678 - Loading comments... 679 - </div> 689 + this.commentsContainer.innerHTML = ` 690 + <div class="sequoia-loading"> 691 + <span class="sequoia-loading-spinner"></span> 692 + Loading comments... 680 693 </div> 681 694 `; 682 695 break; 683 696 684 697 case "no-document": 685 - this.shadow.innerHTML = ` 686 - ${styleTag} 687 - <div class="sequoia-comments-container"> 688 - <div class="sequoia-warning"> 689 - No document found. Add a <code>&lt;link rel="site.standard.document" href="at://..."&gt;</code> tag to your page. 690 - </div> 698 + this.commentsContainer.innerHTML = ` 699 + <div class="sequoia-warning"> 700 + No document found. Add a <code>&lt;link rel="site.standard.document" href="at://..."&gt;</code> tag to your page. 691 701 </div> 692 702 `; 703 + if (this.hide) { 704 + this.commentsContainer.style.display = 'none'; 705 + } 693 706 break; 694 707 695 708 case "no-comments-enabled": 696 - this.shadow.innerHTML = ` 697 - ${styleTag} 698 - <div class="sequoia-comments-container"> 699 - <div class="sequoia-empty"> 700 - Comments are not enabled for this post. 701 - </div> 709 + this.commentsContainer.innerHTML = ` 710 + <div class="sequoia-empty"> 711 + Comments are not enabled for this post. 702 712 </div> 703 713 `; 704 714 break; 705 715 706 716 case "empty": 707 - this.shadow.innerHTML = ` 708 - ${styleTag} 709 - <div class="sequoia-comments-container"> 710 - <div class="sequoia-comments-header"> 711 - <h3 class="sequoia-comments-title">Comments</h3> 712 - <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 713 - ${BLUESKY_ICON} 714 - Reply on Bluesky 715 - </a> 716 - </div> 717 - <div class="sequoia-empty"> 718 - No comments yet. Be the first to reply on Bluesky! 719 - </div> 717 + this.commentsContainer.innerHTML = ` 718 + <div class="sequoia-comments-header"> 719 + <h3 class="sequoia-comments-title">Comments</h3> 720 + <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 721 + ${BLUESKY_ICON} 722 + Reply on Bluesky 723 + </a> 724 + </div> 725 + <div class="sequoia-empty"> 726 + No comments yet. Be the first to reply on Bluesky! 720 727 </div> 721 728 `; 722 729 break; 723 730 724 731 case "error": 725 - this.shadow.innerHTML = ` 726 - ${styleTag} 727 - <div class="sequoia-comments-container"> 728 - <div class="sequoia-error"> 729 - Failed to load comments: ${escapeHtml(this.state.message)} 730 - </div> 732 + this.commentsContainer.innerHTML = ` 733 + <div class="sequoia-error"> 734 + Failed to load comments: ${escapeHtml(this.state.message)} 731 735 </div> 732 736 `; 733 737 break; ··· 740 744 .join(""); 741 745 const commentCount = this.countComments(replies); 742 746 743 - this.shadow.innerHTML = ` 744 - ${styleTag} 745 - <div class="sequoia-comments-container"> 746 - <div class="sequoia-comments-header"> 747 - <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3> 748 - <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 749 - ${BLUESKY_ICON} 750 - Reply on Bluesky 751 - </a> 752 - </div> 753 - <div class="sequoia-comments-list"> 754 - ${threadsHtml} 755 - </div> 747 + this.commentsContainer.innerHTML = ` 748 + <div class="sequoia-comments-header"> 749 + <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3> 750 + <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 751 + ${BLUESKY_ICON} 752 + Reply on Bluesky 753 + </a> 754 + </div> 755 + <div class="sequoia-comments-list"> 756 + ${threadsHtml} 756 757 </div> 757 758 `; 758 759 break;
+56 -55
packages/cli/src/components/sequoia-comments.js
··· 14 14 * Attributes: 15 15 * - document-uri: AT Protocol URI for the document (optional if link tag exists) 16 16 * - depth: Maximum depth of nested replies to fetch (default: 6) 17 + * - hide: Set to "auto" to hide if no document link is detected 17 18 * 18 19 * CSS Custom Properties: 19 20 * - --sequoia-fg-color: Text color (default: #1f2937) ··· 573 574 class SequoiaComments extends BaseElement { 574 575 constructor() { 575 576 super(); 576 - this.shadow = this.attachShadow({ mode: "open" }); 577 + const shadow = this.attachShadow({ mode: "open" }); 578 + 579 + const styleTag = document.createElement("style"); 580 + shadow.appendChild(styleTag); 581 + styleTag.innerText = styles; 582 + 583 + const container = document.createElement("div"); 584 + shadow.appendChild(container); 585 + container.className = "sequoia-comments-container"; 586 + container.part = "container"; 587 + 588 + this.commentsContainer = container; 577 589 this.state = { type: "loading" }; 578 590 this.abortController = null; 591 + 579 592 } 580 593 581 594 static get observedAttributes() { 582 - return ["document-uri", "depth"]; 595 + return ["document-uri", "depth", "hide"]; 583 596 } 584 597 585 598 connectedCallback() { ··· 614 627 get depth() { 615 628 const depthAttr = this.getAttribute("depth"); 616 629 return depthAttr ? parseInt(depthAttr, 10) : 6; 630 + } 631 + 632 + get hide() { 633 + const hideAttr = this.getAttribute("hide"); 634 + return hideAttr === "auto"; 617 635 } 618 636 619 637 async loadComments() { ··· 666 684 } 667 685 668 686 render() { 669 - const styleTag = `<style>${styles}</style>`; 670 - 671 687 switch (this.state.type) { 672 688 case "loading": 673 - this.shadow.innerHTML = ` 674 - ${styleTag} 675 - <div class="sequoia-comments-container"> 676 - <div class="sequoia-loading"> 677 - <span class="sequoia-loading-spinner"></span> 678 - Loading comments... 679 - </div> 689 + this.commentsContainer.innerHTML = ` 690 + <div class="sequoia-loading"> 691 + <span class="sequoia-loading-spinner"></span> 692 + Loading comments... 680 693 </div> 681 694 `; 682 695 break; 683 696 684 697 case "no-document": 685 - this.shadow.innerHTML = ` 686 - ${styleTag} 687 - <div class="sequoia-comments-container"> 688 - <div class="sequoia-warning"> 689 - No document found. Add a <code>&lt;link rel="site.standard.document" href="at://..."&gt;</code> tag to your page. 690 - </div> 698 + this.commentsContainer.innerHTML = ` 699 + <div class="sequoia-warning"> 700 + No document found. Add a <code>&lt;link rel="site.standard.document" href="at://..."&gt;</code> tag to your page. 691 701 </div> 692 702 `; 703 + if (this.hide) { 704 + this.commentsContainer.style.display = 'none'; 705 + } 693 706 break; 694 707 695 708 case "no-comments-enabled": 696 - this.shadow.innerHTML = ` 697 - ${styleTag} 698 - <div class="sequoia-comments-container"> 699 - <div class="sequoia-empty"> 700 - Comments are not enabled for this post. 701 - </div> 709 + this.commentsContainer.innerHTML = ` 710 + <div class="sequoia-empty"> 711 + Comments are not enabled for this post. 702 712 </div> 703 713 `; 704 714 break; 705 715 706 716 case "empty": 707 - this.shadow.innerHTML = ` 708 - ${styleTag} 709 - <div class="sequoia-comments-container"> 710 - <div class="sequoia-comments-header"> 711 - <h3 class="sequoia-comments-title">Comments</h3> 712 - <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 713 - ${BLUESKY_ICON} 714 - Reply on Bluesky 715 - </a> 716 - </div> 717 - <div class="sequoia-empty"> 718 - No comments yet. Be the first to reply on Bluesky! 719 - </div> 717 + this.commentsContainer.innerHTML = ` 718 + <div class="sequoia-comments-header"> 719 + <h3 class="sequoia-comments-title">Comments</h3> 720 + <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 721 + ${BLUESKY_ICON} 722 + Reply on Bluesky 723 + </a> 724 + </div> 725 + <div class="sequoia-empty"> 726 + No comments yet. Be the first to reply on Bluesky! 720 727 </div> 721 728 `; 722 729 break; 723 730 724 731 case "error": 725 - this.shadow.innerHTML = ` 726 - ${styleTag} 727 - <div class="sequoia-comments-container"> 728 - <div class="sequoia-error"> 729 - Failed to load comments: ${escapeHtml(this.state.message)} 730 - </div> 732 + this.commentsContainer.innerHTML = ` 733 + <div class="sequoia-error"> 734 + Failed to load comments: ${escapeHtml(this.state.message)} 731 735 </div> 732 736 `; 733 737 break; ··· 740 744 .join(""); 741 745 const commentCount = this.countComments(replies); 742 746 743 - this.shadow.innerHTML = ` 744 - ${styleTag} 745 - <div class="sequoia-comments-container"> 746 - <div class="sequoia-comments-header"> 747 - <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3> 748 - <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 749 - ${BLUESKY_ICON} 750 - Reply on Bluesky 751 - </a> 752 - </div> 753 - <div class="sequoia-comments-list"> 754 - ${threadsHtml} 755 - </div> 747 + this.commentsContainer.innerHTML = ` 748 + <div class="sequoia-comments-header"> 749 + <h3 class="sequoia-comments-title">${commentCount} Comment${commentCount !== 1 ? "s" : ""}</h3> 750 + <a href="${this.state.postUrl}" target="_blank" rel="noopener noreferrer" class="sequoia-reply-button"> 751 + ${BLUESKY_ICON} 752 + Reply on Bluesky 753 + </a> 754 + </div> 755 + <div class="sequoia-comments-list"> 756 + ${threadsHtml} 756 757 </div> 757 758 `; 758 759 break;