Skip to content

Commit 973aa2e

Browse files
committed
Add bookmarklets for Kotlin GitHub PR actions
1 parent 0f99952 commit 973aa2e

1 file changed

Lines changed: 177 additions & 0 deletions

File tree

kotlin/github/index.html

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width">
6+
<title>Kotlin/GitHub Bookmarklets</title>
7+
8+
<style type="text/css">
9+
body {
10+
background-color: #f0f0f0;
11+
margin: 0;
12+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
13+
}
14+
15+
.container {
16+
max-width: 920px;
17+
margin: 0 auto;
18+
padding: 20px;
19+
background: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
20+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
21+
min-height: 100%;
22+
}
23+
24+
.bookmarklet {
25+
border: 1px solid #e0e0e0;
26+
border-radius: 8px;
27+
padding: 16px;
28+
margin-bottom: 16px;
29+
background: #fff;
30+
}
31+
32+
.bookmarklet-link {
33+
/*font-size: 1.1em;*/
34+
/*font-weight: bold;*/
35+
/*text-decoration: none;*/
36+
color: #7F52FF;
37+
}
38+
39+
.bookmarklet-link:hover {
40+
text-decoration: underline;
41+
}
42+
43+
.bookmarklet-action {
44+
display: inline-block;
45+
margin-top: 6px;
46+
padding: 2px 8px;
47+
background: #f0ecff;
48+
border: 1px solid #d8d0f0;
49+
border-radius: 4px;
50+
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
51+
font-size: 0.8em;
52+
/*color: #5a3fbf;*/
53+
}
54+
55+
.bookmarklet-description {
56+
margin-top: 8px;
57+
color: #555;
58+
line-height: 1.5;
59+
}
60+
61+
.prefix-input {
62+
width: 100%;
63+
box-sizing: border-box;
64+
padding: 10px 12px;
65+
margin-bottom: 16px;
66+
font-size: 1em;
67+
font-family: inherit;
68+
border: 1px solid #d8d0f0;
69+
border-radius: 8px;
70+
background: #f5f2ff;
71+
color: #333;
72+
outline: none;
73+
}
74+
75+
.prefix-input:focus {
76+
border-color: #7F52FF;
77+
box-shadow: 0 0 0 2px rgba(127, 82, 255, 0.15);
78+
}
79+
</style>
80+
</head>
81+
<body>
82+
<div class="container">
83+
<h1 style="color: #7F52FF;">Bookmarklets for Kotlin Pull requests on GitHub</h1>
84+
85+
<strong>How to use:</strong>
86+
<ol style="margin-top: 6px; padding-left: 20px; color: #444; line-height: 1.7;">
87+
<li>Drag a bookmarklet link below to your browser's bookmarks bar.</li>
88+
<li>Navigate to a Pull Request page on GitHub.</li>
89+
<li>Click the bookmarklet in the bookmarks bar. It will post the corresponding command into the PR comment field and submit it.<br/>
90+
Uncheck the following checkbox if you don't want the command to be submitted automatically.</li>
91+
</ol>
92+
<label style="display: inline-flex; align-items: center; gap: 6px; margin-bottom: 16px; font-size: 0.95em; color: #555; cursor: pointer;">
93+
<input id="submit-command" type="checkbox" checked> Submit commands immediately.
94+
</label>
95+
96+
<p style="color: #444; line-height: 1.7; margin-top: 4px;">
97+
<strong>Tip:</strong> A bookmarklet can also be invoked from the address bar: activate it with a click or a shortcut (<code>Cmd + L</code> / <code>Ctrl + L</code>), start typing the bookmark's name, select it, and press Enter.
98+
<br/>
99+
<strong>Tip:</strong> Add a unique prefix (e.g. "<code>k__ </code>") using the input below so your bookmarklets are easy to find.
100+
</p>
101+
102+
<input id="prefix" class="prefix-input" type="text" placeholder="Bookmarklets title prefix">
103+
104+
<div id="bookmarklets">
105+
</div>
106+
</div>
107+
</body>
108+
<script type="module">
109+
function command(action, title, description) {
110+
return { action, title, description };
111+
}
112+
113+
function htmlfy(string) {
114+
return string
115+
.replace(/\n/g, "<br/>")
116+
.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>")
117+
}
118+
119+
const commands = [
120+
command('/test-public', 'Start public Aggregate', 'Starts public Aggregate (when targeting release, it will start public release Aggregate for a matching release).'),
121+
command('/dry-run', 'Start safe-merge in dry run', 'Starts safe-merge in dry run, which will run a full set of checks with the rebased latest master (not allowed when targeting release branch).'),
122+
command('/safe-merge', 'Start safe-merge with “rebase and merge” mode', 'Starts safe-merge with “rebase and merge” mode, with optional parameter:\n**--fixup** will first try to squash fixups and force push the branch, then trigger safe merge\nExample: \n/**safe-merge --fixup**.'),
123+
command('/safe-merge --fixup', 'Autosquash of "fixup!" commits and start safe-merge with “rebase and merge” mode', 'Starts safe-merge with “rebase and merge” mode, with optional parameter:\n**--fixup** will first try to squash fixups and force push the branch, then trigger safe merge\nExample: \n/**safe-merge --fixup**.'),
124+
command('/safe-squash-merge', 'Start safe-merge with "squash" mode', 'Starts safe-merge with "squash" mode, with two optional parameters:\n**--title=** sets the first-line commit title, if not specified, the PR title is used\n**--message=** sets the commit body message, if not specified, the PR description is used\nExample: \n**/safe-squash-merge --title="Update dependency X to version Y" --message="^KT-XYZ"**.'),
125+
command('/codeowners', 'Trigger code owners verification', 'Triggers code owners verification. Useful if the previous check failed unexpectedly or is missing.'),
126+
command('/fixup', 'Perform autosquash of "fixup!" commits and force-push the branch', 'Performs autosquash of "fixup!" commits and force-pushes the branch. It\'s not supported for contributions from forks.')
127+
];
128+
129+
let bookmarklets = document.getElementById("bookmarklets");
130+
let prefixInput = document.getElementById("prefix");
131+
let submitCheckbox = document.getElementById("submit-command");
132+
const submitCode = `document.querySelector('#new_comment_form button.btn-primary.btn').click();`
133+
134+
function showBookmarklets() {
135+
const prefix = prefixInput.value;
136+
bookmarklets.innerHTML = '';
137+
for (const command of commands) {
138+
const title = '' + prefix + command.title;
139+
const submit = submitCheckbox.checked ? submitCode : '';
140+
141+
// language=JavaScript
142+
const js = `(() => {
143+
if (!/^https:\\/\\/github\\.com\\/JetBrains\\/kotlin\\/pull\\/\\d+$/.test(location.href)) {
144+
alert('Nothing to do on this page.');
145+
return;
146+
}
147+
let t = '${command.action}';
148+
let f = document.querySelector('#new_comment_field');
149+
if (f.value) {
150+
alert('The input for comments is not empty!');
151+
return;
152+
}
153+
f.value = t;
154+
f.dispatchEvent(new Event('change', {bubbles: true}));
155+
${submit}
156+
})()`.replace(/\s+/g, ' ');
157+
158+
let node = document.createElement('div');
159+
160+
// language=HTML
161+
node.innerHTML =
162+
`<div class="bookmarklet">
163+
<a class="bookmarklet-link" href="javascript:${js}">${title}</a>
164+
<div><code class="bookmarklet-action">${command.action}</code></div>
165+
<div class="bookmarklet-description">
166+
${htmlfy(command.description)}
167+
</div>
168+
</div>`;
169+
bookmarklets.appendChild(node);
170+
}
171+
}
172+
173+
prefixInput.addEventListener('input', showBookmarklets);
174+
submitCheckbox.addEventListener('change', showBookmarklets);
175+
showBookmarklets();
176+
</script>
177+
</html>

0 commit comments

Comments
 (0)