From 5dde3efaa181915ea33652c78379d1c8668d6a51 Mon Sep 17 00:00:00 2001 From: Matthias Thalmann Date: Sun, 15 Jun 2025 10:56:21 +0200 Subject: [PATCH] chore(pipelines): add release and pr workflows --- .github/workflows/pr.yml | 28 +++++++++++++++++ .github/workflows/release.yml | 58 +++++++++++++++++++++++++++++++++++ .gitignore | 2 +- dist/tree.min.js | 8 ----- dist/treejs.min.css | 1 - 5 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml delete mode 100644 dist/tree.min.js delete mode 100644 dist/treejs.min.css diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..3282be8 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,28 @@ +name: Pull Request + +on: + pull_request: + branches: ['master'] + +jobs: + codestyle: + runs-on: ubuntu-latest + + name: Codestyle + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + run: npm ci + + - name: Check prettier + run: npx prettier --check . + + - name: Check eslint + run: npx eslint --max-warnings 0 . diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1a47ab3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,58 @@ +name: Release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + +permissions: + contents: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Generate changelog + run: | + npm i -g conventional-changelog-cli@^3.0.0 + conventional-changelog -p angular -o CHANGELOG.md -r 2 + tail -n +2 CHANGELOG.md > CHANGELOG #remove first line + sed -i -e '/./,$!d' -e :a -e '/^\n*$/{$d;N;ba' -e '}' CHANGELOG #trim empty lines + + - name: Build + run: | + npm ci + npm run build + cd dist + zip -r ../release.zip * + + - name: Release + uses: actions/create-release@v1 + id: create_release + with: + draft: false + prerelease: false + release_name: TreeJS ${{ env.RELEASE_VERSION }} + tag_name: ${{ env.RELEASE_VERSION }} + body_path: CHANGELOG + env: + GITHUB_TOKEN: ${{ github.token }} + - name: Upload release artifact + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ github.token }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./release.zip + asset_name: TreeJS-${{ env.RELEASE_VERSION }}.zip + asset_content_type: application/zip diff --git a/.gitignore b/.gitignore index 5273281..51b9af5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output -# dist +dist tmp /out-tsc diff --git a/dist/tree.min.js b/dist/tree.min.js deleted file mode 100644 index df3e143..0000000 --- a/dist/tree.min.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * TreeJS is a JavaScript library for displaying TreeViews - * on the web. - * - * @author Matthias Thalmann - * @copyright Matthias Thalmann - */ -const TreeUtil={default_leaf_icon:"🖹",default_parent_icon:"🗁",default_open_icon:"",default_close_icon:"",isDOM(e){try{return e instanceof HTMLElement}catch{return"object"==typeof e&&1===e.nodeType&&"object"==typeof e.style&&"object"==typeof e.ownerDocument}},getProperty:(e,t,n)=>void 0===e[t]?n:e[t],expandNode(e){e.setExpanded(!0),e.isLeaf()||e.getChildren().forEach((e=>{TreeUtil.expandNode(e)}))},collapseNode(e){e.setExpanded(!1),e.isLeaf()||e.getChildren().forEach((e=>{TreeUtil.collapseNode(e)}))},getSelectedNodesForNode(e){if(!(e instanceof TreeNode))throw new Error("Parameter 1 must be of type TreeNode");const t=new Array;return e.isSelected()&&t.push(e),e.getChildren().forEach((e=>{e.isSelected()&&-1===t.indexOf(e)&&t.push(e),e.isLeaf()||TreeUtil.getSelectedNodesForNode(e).forEach((e=>{-1===t.indexOf(e)&&t.push(e)}))})),t}},TreeConfig={leaf_icon:TreeUtil.default_leaf_icon,parent_icon:TreeUtil.default_parent_icon,open_icon:TreeUtil.default_open_icon,close_icon:TreeUtil.default_close_icon,context_menu:void 0};function TreeNode(e,t){const n=new Array,o=new Array;let i=!0,r=!0,s=!1;if(e){if("string"!=typeof e&&"function"!=typeof e.toString)throw new Error("Parameter 1 must be of type String or Object, where it must have the function toString()")}else e="";t&&"object"==typeof t?(i=TreeUtil.getProperty(t,"expanded",!0),r=TreeUtil.getProperty(t,"enabled",!0),s=TreeUtil.getProperty(t,"selected",!1)):t={},this.addChild=function(e){if(TreeUtil.getProperty(t,"allowsChildren",!0)){if(!(e instanceof TreeNode))throw new Error("Parameter 1 must be of type TreeNode");n.push(e),Object.defineProperty(e,"parent",{value:this,writable:!1,enumerable:!0,configurable:!0})}else console.warn("Option allowsChildren is set to false, no child added")},this.removeChildPos=function(e){void 0!==n[e]&&void 0!==n[e]&&n.splice(e,1)},this.removeChild=function(e){if(!(e instanceof TreeNode))throw new Error("Parameter 1 must be of type TreeNode");this.removeChildPos(this.getIndexOfChild(e))},this.getChildren=function(){return n},this.getChildCount=function(){return n.length},this.getIndexOfChild=function(e){for(let t=0;t{let t=e.target;for(;void 0===t.tj_node||t.classList.contains("tj_container");)t=t.parentElement;const n=t.tj_node;if(void 0!==n&&n.isEnabled())if(!1===e.ctrlKey&&(n.isLeaf()?n.open():(n.toggleExpanded(),o.reload()),n.on("click")(e,n)),!0===e.ctrlKey)n.toggleSelected(),o.reload();else{const e=n.getRoot();e instanceof TreeNode&&TreeUtil.getSelectedNodesForNode(e).forEach((e=>{e.setSelected(!1)})),n.setSelected(!0),o.reload()}})),r.addEventListener("contextmenu",(e=>{let t=e.target;for(;void 0===t.tj_node||t.classList.contains("tj_container");)t=t.parentElement;const n=t.tj_node;void 0!==n&&(void 0!==n.getListener("contextmenu")?(n.on("contextmenu")(e,n),e.preventDefault()):"function"==typeof TreeConfig.context_menu&&(TreeConfig.context_menu(e,n),e.preventDefault()))})),e.isLeaf()&&!TreeUtil.getProperty(e.getOptions(),"forceParent",!1)){let o="",i=TreeUtil.getProperty(e.getOptions(),"icon","");""!==i||""!=(i=TreeUtil.getProperty(n,"leaf_icon",""))?o+=`${i}`:o+=`${TreeConfig.leaf_icon}`,r.innerHTML=`${o+e.toString()}`,r.classList.add("tj_leaf"),t.appendChild(r)}else{let o="";e.isExpanded()?o+=`${TreeConfig.open_icon}`:o+=`${TreeConfig.close_icon}`;const s=TreeUtil.getProperty(e.getOptions(),"icon","");if(""!==s||""!=(s=TreeUtil.getProperty(n,"parent_icon",""))?o+=`${s}`:o+=`${TreeConfig.parent_icon}`,r.innerHTML=`${o+e.toString()}`,t.appendChild(r),e.isExpanded()){const n=document.createElement("ul");e.getChildren().forEach((e=>{n.appendChild(i(e))})),t.appendChild(n)}}return t}n&&"object"==typeof n||(n={}),this.setRoot=function(t){e instanceof TreeNode&&(e=t)},this.getRoot=function(){return e},this.expandAllNodes=function(){e.setExpanded(!0),e.getChildren().forEach((e=>{TreeUtil.expandNode(e)}))},this.expandPath=function(e){if(!(e instanceof TreePath))throw new Error("Parameter 1 must be of type TreePath");e.getPath().forEach((e=>{e.setExpanded(!0)}))},this.collapseAllNodes=function(){e.setExpanded(!1),e.getChildren().forEach((e=>{TreeUtil.collapseNode(e)}))},this.setContainer=function(e){if(TreeUtil.isDOM(e))t=e;else if((e=document.querySelector(e))instanceof Array&&(e=e[0]),!TreeUtil.isDOM(e))throw new Error("Parameter 1 must be either DOM-Object or CSS-QuerySelector (#, .)")},this.getContainer=function(){return t},this.setOptions=function(e){"object"==typeof e&&(n=e)},this.changeOption=function(e,t){n[e]=t},this.getOptions=function(){return n},this.getSelectedNodes=function(){return TreeUtil.getSelectedNodesForNode(e)},this.reload=function(){if(null===t)return void console.warn("No container specified");t.classList.add("tj_container");const o=document.createElement("ul");TreeUtil.getProperty(n,"show_root",!0)?o.appendChild(i(e)):e.getChildren().forEach((e=>{o.appendChild(i(e))})),t.innerHTML="",t.appendChild(o)},void 0!==t&&this.reload()}function TreePath(e,t){let n=new Array;this.setPath=function(e,t){for(n=new Array;void 0!==t&&!t.equals(e);)n.push(t),t=t.parent;if(!t.equals(e))throw n=new Array,new Error("Node is not contained in the tree of root");return n.push(e),n=n.reverse(),n},this.getPath=function(){return n},this.toString=function(){return n.join(" - ")},e instanceof TreeNode&&t instanceof TreeNode&&this.setPath(e,t)}function test(){return console.log("Test function executed"),"Test completed"} \ No newline at end of file diff --git a/dist/treejs.min.css b/dist/treejs.min.css deleted file mode 100644 index 1e1f7dc..0000000 --- a/dist/treejs.min.css +++ /dev/null @@ -1 +0,0 @@ -.tj_container *{box-sizing:border-box;position:relative}.tj_container ul{list-style-type:none;padding-left:2em}.tj_container>ul:first-of-type{padding:0}.tj_container li span.tj_description{-webkit-touch-callout:none;border-radius:2px;cursor:pointer;display:block;padding:2px 5px;text-align:left;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.tj_container li span.tj_description:hover{background-color:#ccc}.tj_container li span.tj_icon,.tj_container li span.tj_mod_icon{display:inline-block;margin-right:.5em}.tj_container li span.tj_mod_icon,.tj_container li span.tj_mod_icon *{width:1em}.tj_container li span.tj_description.tj_leaf{margin-left:1.5em}.tj_container li[disabled=""]{color:#b5b5b5}.tj_container li[disabled=""]:hover span.tj_description{background-color:inherit;cursor:default}.tj_container span.tj_description.selected{background-color:#2b2b2b;color:#fff}.tj_container span.tj_description.selected:hover{background-color:#606060} \ No newline at end of file