├── link_icon.png
├── style.css
├── manifest.json
├── README.md
├── link_index.html
└── app.js
/link_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/parthpanchal123/Linkaro/HEAD/link_icon.png
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | width: 500px;
3 | height: 500px;
4 | border-top: 1px solid #000;
5 | font-family: "Poppins", sans-serif;
6 | }
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Linkaro",
3 | "version": "0.0.1",
4 | "manifest_version": 2,
5 | "browser_action": {
6 | "default_popup": "link_index.html",
7 | "default_icon": "link_icon.png"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Linkaro : A browser extension to store and share your social links easily.
2 |
3 | ## Working
4 |
5 | - Add in your urls and hit the pencil icon .
6 | - The urls will be saved automatically in your browsers local storage
7 | - Now just hit the copy button to copy the link to your clipboard and share the link easily .
8 |
9 | ## Screenshots
10 |
11 | 
12 |
13 | ## How to use the extension
14 |
15 | - Clone the repository
16 |
17 | `git clone parthpanchal123/Linkaro`
18 |
19 | - Go to extensions in your browser
20 |
21 | 
22 |
23 | - Enable developer options
24 |
25 | 
26 |
27 | - Click on load unpacked
28 |
29 | 
30 |
31 | - Simply select the folder where you cloned the Linkaro folder . The extension should be visible in your browser .
32 |
33 | ### Do 🌟 the repo if you liked the extension .
34 |
--------------------------------------------------------------------------------
/link_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Linkaro
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
Linkaro : Manage your links easily
23 |
24 |
25 |
26 |
27 |
28 |
29 |
33 |
34 |
35 |
36 |
37 | Click on the edit button to save after making
38 | required changes
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | // Button Refernce for add new field btn
2 | const addNewBtn = document.getElementById("addNewBtn");
3 |
4 | // The div that contains all the fields
5 | const linksDiv = document.querySelector(".links-area");
6 |
7 | /**
8 | * @param {String} key The name of the field
9 | * @param {String} linkData The data of the field
10 | */
11 | const saveToLocalStorage = (key, linkData) => {
12 | if (!linkData) return;
13 | localStorage.setItem(key, linkData);
14 | };
15 |
16 | /**
17 | * @param {String} urlData The linkdata of the field
18 | */
19 | const copyToClipboard = async (urlData) => {
20 | try {
21 | if (!urlData) {
22 | alert("No link to copy ❌ ");
23 | return;
24 | }
25 | await navigator.clipboard.writeText(urlData);
26 | showalert(urlData);
27 | } catch (error) {
28 | alert("Did you give the clipboard permission ?");
29 | }
30 | };
31 |
32 | /**
33 | * @param {String} linkData The data of the field
34 | */
35 | const showalert = (linkData) => {
36 | alert(linkData + " copied to clipboard ✔ ");
37 | };
38 |
39 | const loadAllFromLocalStorage = () => {
40 | const defaultFields = [
41 | "Github",
42 | "Linkedin",
43 | "Twitter",
44 | "Portfolio",
45 | "Email",
46 | "Dev",
47 | "Dribbble",
48 | ];
49 | // An array for custom fields
50 | let customFields = JSON.parse(localStorage.getItem("customFields")) ?? [];
51 |
52 | if (customFields.length != 0) {
53 | customFields.forEach((field) => {
54 | renderFieldsFromLocalStorage({ newFieldName: field, isNewField: false });
55 | });
56 | } else {
57 | localStorage.setItem("customFields", JSON.stringify(defaultFields));
58 | }
59 | };
60 | /**
61 | * @param {String} newFieldName The name of the field
62 | * @param {Boolean} isNewField A boolean to check if the field is new or not
63 | */
64 | const renderFieldsFromLocalStorage = ({ newFieldName, isNewField }) => {
65 | const newField = document.createElement("div");
66 | newField.classList.add(
67 | "flex",
68 | "flex-row",
69 | "justify-center",
70 | "items-center",
71 | "ml-3"
72 | );
73 |
74 | const iconsHash = {
75 | Github: "fab fa-github",
76 | Linkedin: "fab fa-linkedin",
77 | Twitter: "fab fa-twitter",
78 | Portfolio: "fas fa-globe",
79 | Email: "fas fa-envelope",
80 | Dev: "fab fa-dev",
81 | Dribbble: "fab fa-dribbble",
82 | };
83 |
84 | const newIcon = document.createElement("i");
85 | newIcon.style.fontSize = "28px";
86 |
87 | if (iconsHash[newFieldName]) {
88 | newIcon.classList.add(...iconsHash[newFieldName].split(" "));
89 | } else {
90 | newIcon.classList.add("fas", "fa-link");
91 | }
92 |
93 | const newEditIcon = document.createElement("i");
94 | newEditIcon.classList.add("fas", "fa-edit");
95 |
96 | const newCopyIcon = document.createElement("i");
97 | newCopyIcon.classList.add("fas", "fa-copy");
98 |
99 | const newFieldInput = document.createElement("input");
100 | newFieldInput.classList.add(
101 | "w-3/5",
102 | "ml-4",
103 | "px-2",
104 | "py-2",
105 | "shadow-md",
106 | "rounded-md",
107 | "text-left"
108 | );
109 |
110 | newFieldInput.setAttribute("placeholder", newFieldName);
111 | newFieldInput.setAttribute("id", newFieldName);
112 | newFieldInput.value = localStorage.getItem(newFieldName);
113 | newFieldInput.setAttribute("type", "text");
114 |
115 | const newFieldEditBtn = document.createElement("button");
116 | newFieldEditBtn.classList.add(
117 | "m-2",
118 | "bg-blue-500",
119 | "hover:bg-blue-700",
120 | "text-white",
121 | "font-bold",
122 | "py-2",
123 | "px-4",
124 | "rounded-md",
125 | "shadow-md"
126 | );
127 | newFieldEditBtn.setAttribute("id", newFieldName + "EditBtn");
128 |
129 | newFieldEditBtn.appendChild(newEditIcon);
130 |
131 | newFieldEditBtn.addEventListener("click", () => {
132 | const data = document.getElementById(newFieldName).value;
133 | saveToLocalStorage(newFieldName, data);
134 | });
135 |
136 | const newFieldCopyBtn = document.createElement("button");
137 | newFieldCopyBtn.classList.add(
138 | "bg-blue-500",
139 | "hover:bg-blue-700",
140 | "text-white",
141 | "font-bold",
142 | "py-2",
143 | "px-4",
144 | "rounded-md",
145 | "shadow-md"
146 | );
147 |
148 | newFieldCopyBtn.setAttribute("id", newFieldName + "CopyBtn");
149 | newFieldCopyBtn.appendChild(newCopyIcon);
150 |
151 | newFieldCopyBtn.addEventListener("click", () => {
152 | const data = document.getElementById(newFieldName).value;
153 | copyToClipboard(data);
154 | });
155 |
156 | newField.appendChild(newIcon);
157 | newField.appendChild(newFieldInput);
158 | newField.appendChild(newFieldEditBtn);
159 | newField.appendChild(newFieldCopyBtn);
160 |
161 | linksDiv.appendChild(newField);
162 |
163 | if (isNewField) {
164 | let existingFields = JSON.parse(localStorage.getItem("customFields"));
165 | existingFields.push(newFieldName);
166 | localStorage.setItem("customFields", JSON.stringify(existingFields));
167 | }
168 | };
169 |
170 | addNewBtn.addEventListener("click", () => {
171 | newFieldName = prompt("Enter a new field name");
172 | if (!newFieldName) return;
173 |
174 | if (isDuplicateField(newFieldName)) return;
175 | renderFieldsFromLocalStorage({ newFieldName, isNewField: true });
176 | });
177 | /**
178 | * @param {String} newLinkName The name of the field
179 | */
180 | const isDuplicateField = (newLinkName) => {
181 | const links = JSON.parse(localStorage.getItem("customFields"));
182 |
183 | if (!links) return;
184 |
185 | if (links.includes(newLinkName)) {
186 | alert("This field already exists");
187 | return true;
188 | }
189 | };
190 |
191 | // Load all the fields from local storage on startup.
192 | document.onload = loadAllFromLocalStorage();
193 |
--------------------------------------------------------------------------------