mirror of
https://github.com/NohamR/Code-to-PDF.git
synced 2026-05-25 04:07:17 +00:00
Completely rearchitect the code renderer
This commit is contained in:
13
index.html
13
index.html
@@ -83,16 +83,17 @@
|
|||||||
</select>
|
</select>
|
||||||
<button id="print">Print</button>
|
<button id="print">Print</button>
|
||||||
</div>
|
</div>
|
||||||
<textarea placeholder="Enter code ..."></textarea>
|
<textarea spellcheck="false" placeholder="Enter code ..."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div id="print-area">
|
<div id="print-area">
|
||||||
<h1 id="document-title">Code</h1>
|
|
||||||
<div id="code-container">
|
<div id="code-container">
|
||||||
<div id="line-nums" class="hljs">
|
<div class="code-line">
|
||||||
<pre>1 </pre>
|
<span class="line-number">1</span>
|
||||||
|
<pre class="code-pre"><code id="code">console.log("Hello World!");</code></pre>
|
||||||
</div>
|
</div>
|
||||||
<div id="code-div">
|
<div class="code-line">
|
||||||
<pre><code id="code">console.log("Hello World!");</code></pre>
|
<span class="line-number">2</span>
|
||||||
|
<pre class="code-pre"><code id="code">console.log("Hello World!");</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
98
index.js
98
index.js
@@ -2,11 +2,11 @@ const printBtn = document.getElementById('print');
|
|||||||
const codeTextArea = document.getElementsByTagName('textarea')[0];
|
const codeTextArea = document.getElementsByTagName('textarea')[0];
|
||||||
const code = document.getElementById('code');
|
const code = document.getElementById('code');
|
||||||
const documentNameInput = document.getElementById('document-name-input');
|
const documentNameInput = document.getElementById('document-name-input');
|
||||||
const documentTitle = document.getElementById('document-title');
|
|
||||||
const languageSelector = document.getElementById('languages');
|
const languageSelector = document.getElementById('languages');
|
||||||
const codeLines = document.getElementById('line-nums');
|
const codeLines = document.getElementById('line-nums');
|
||||||
const themeStylesheet = document.getElementById('theme-style');
|
const themeStylesheet = document.getElementById('theme-style');
|
||||||
const themeSelector = document.getElementById('themes');
|
const themeSelector = document.getElementById('themes');
|
||||||
|
const codeContainer = document.getElementById('code-container');
|
||||||
let selectedLanguage = localStorage.getItem('language') || 'javascript';
|
let selectedLanguage = localStorage.getItem('language') || 'javascript';
|
||||||
let selectedTheme = localStorage.getItem('theme') || 'github-dark';
|
let selectedTheme = localStorage.getItem('theme') || 'github-dark';
|
||||||
let codeText = localStorage.getItem('code') || 'console.log("Hello World")';
|
let codeText = localStorage.getItem('code') || 'console.log("Hello World")';
|
||||||
@@ -15,34 +15,42 @@ let codeText = localStorage.getItem('code') || 'console.log("Hello World")';
|
|||||||
themeStylesheet.setAttribute('href', getStylesheet(selectedTheme));
|
themeStylesheet.setAttribute('href', getStylesheet(selectedTheme));
|
||||||
themeSelector.value = selectedTheme;
|
themeSelector.value = selectedTheme;
|
||||||
code.classList.add('hljs', `language-${selectedLanguage}`);
|
code.classList.add('hljs', `language-${selectedLanguage}`);
|
||||||
code.innerHTML = escape(codeText);
|
escaped = escapeHtml(codeText);
|
||||||
|
code.innerHTML = escaped;
|
||||||
codeTextArea.value = codeText;
|
codeTextArea.value = codeText;
|
||||||
languageSelector.value = selectedLanguage;
|
languageSelector.value = selectedLanguage;
|
||||||
documentTitle.innerHTML = documentNameInput.value || 'Untitled';
|
|
||||||
updateLineNumbers();
|
|
||||||
hljs.configure({
|
hljs.configure({
|
||||||
languages: ['java', 'javascript', 'html', 'typescript', 'cpp']
|
languages: ['java', 'javascript', 'html', 'typescript', 'cpp']
|
||||||
});
|
});
|
||||||
hljs.highlightElement(code);
|
|
||||||
|
updateCode();
|
||||||
|
|
||||||
// Attach event listeners
|
// Attach event listeners
|
||||||
documentNameInput.addEventListener('input', () => {
|
|
||||||
documentTitle.innerHTML = documentNameInput.value || 'Untitled';
|
|
||||||
});
|
|
||||||
|
|
||||||
printBtn.addEventListener('click', () => {
|
printBtn.addEventListener('click', () => {
|
||||||
console.log('Print button clicked.');
|
updateCode();
|
||||||
document.title = documentTitle.textContent || 'code.pdf';
|
let optGroup = themeSelector.options[themeSelector.selectedIndex].parentNode;
|
||||||
|
const lineNumbers = document.querySelectorAll('.line-number');
|
||||||
|
|
||||||
|
if (optGroup.label === 'Dark') {
|
||||||
|
for (let i = 0; i < lineNumbers.length; i++) {
|
||||||
|
lineNumbers[i].style.backgroundColor = '#353b48';
|
||||||
|
lineNumbers[i].style.color = '#dfe6e9';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < lineNumbers.length; i++) {
|
||||||
|
lineNumbers[i].style.backgroundColor = '#dcdde1';
|
||||||
|
lineNumbers[i].style.color = '#2d3436';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
document.title = documentNameInput.value || 'Code';
|
||||||
window.print();
|
window.print();
|
||||||
document.title = 'Code Formatter';
|
document.title = 'Convert Code to PDF Online: Free Tool for Programming Languages';
|
||||||
});
|
});
|
||||||
|
|
||||||
codeTextArea.addEventListener('input', () => {
|
codeTextArea.addEventListener('input', () => {
|
||||||
codeText = codeTextArea.value;
|
codeText = codeTextArea.value;
|
||||||
localStorage.setItem('code', codeText);
|
localStorage.setItem('code', codeText);
|
||||||
code.innerHTML = escape(codeText);
|
code.innerHTML = escapeHtml(codeText);
|
||||||
updateLineNumbers();
|
|
||||||
hljs.highlightElement(code);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
languageSelector.addEventListener('change', () => {
|
languageSelector.addEventListener('change', () => {
|
||||||
@@ -50,44 +58,50 @@ languageSelector.addEventListener('change', () => {
|
|||||||
selectedLanguage = languageSelector.value;
|
selectedLanguage = languageSelector.value;
|
||||||
localStorage.setItem('language', selectedLanguage);
|
localStorage.setItem('language', selectedLanguage);
|
||||||
code.classList.add(`language-${selectedLanguage}`);
|
code.classList.add(`language-${selectedLanguage}`);
|
||||||
hljs.highlightElement(code);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
themeSelector.addEventListener('change', () => {
|
themeSelector.addEventListener('change', () => {
|
||||||
selectedTheme = themeSelector.value;
|
selectedTheme = themeSelector.value;
|
||||||
themeStylesheet.href = getStylesheet(selectedTheme);
|
themeStylesheet.href = getStylesheet(selectedTheme);
|
||||||
localStorage.setItem('theme', selectedTheme);
|
localStorage.setItem('theme', selectedTheme);
|
||||||
hljs.highlightElement(code);
|
|
||||||
documentTitle.innerHTML = documentNameInput.value || 'Untitled';
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('beforeprint', event => {
|
|
||||||
document.body.classList.add('hljs');
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('afterprint', event => {
|
|
||||||
document.body.classList.remove('hljs');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
function escape(s) {
|
function escapeHtml(text) {
|
||||||
return s.replace(/[^0-9A-Za-z ]/g, c => `&#${c.charCodeAt(0)};`);
|
return text
|
||||||
}
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
function updateLineNumbers() {
|
.replace(/>/g, ">")
|
||||||
const lines = codeTextArea.value.split('\n');
|
.replace(/"/g, """)
|
||||||
const numLines = lines.length;
|
.replace(/'/g, "'");
|
||||||
const numLinesDigits = numLines.toString().length;
|
|
||||||
let html = '';
|
|
||||||
for (let i = 0; i < numLines; i++) {
|
|
||||||
html += `<pre>${(i + 1).toString().padStart(numLinesDigits)} </pre>`;
|
|
||||||
for (let j = 0; j < lines[i].length / 98 - 1; j++) {
|
|
||||||
html += `<pre>${''.padStart(numLinesDigits)} </pre>`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
codeLines.innerHTML = html;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStylesheet(style) {
|
function getStylesheet(style) {
|
||||||
return `//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/${style}.min.css`;
|
return `//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.5.1/styles/${style}.min.css`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createCodeLine(lineNumber, lineContent) {
|
||||||
|
lineContent = lineContent || ' ';
|
||||||
|
const code = `<code id="code" class="hljs language-${selectedLanguage}">${lineContent}</code>`;
|
||||||
|
return `<div class="code-line"><span class="line-number">${lineNumber}</span><pre class="code-pre">${code}</pre></div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCode() {
|
||||||
|
const lines = codeTextArea.value.split('\n');
|
||||||
|
const numLines = lines.length;
|
||||||
|
let formattedCode = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
const lineNumber = (i + 1).toString().padStart(Math.floor(Math.log10(numLines)) + 1, ' ');
|
||||||
|
const lineContent = escapeHtml(lines[i]);
|
||||||
|
const codeLine = createCodeLine(lineNumber, lineContent);
|
||||||
|
formattedCode += codeLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
codeContainer.innerHTML = formattedCode;
|
||||||
|
hljs.highlightAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
88
styles.css
88
styles.css
@@ -38,17 +38,27 @@ input {
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
border-width: 0;
|
border-width: 0;
|
||||||
background-color: #006ed9;
|
background-color: #487eb0;
|
||||||
color: white;
|
color: white;
|
||||||
|
max-width: 100px;
|
||||||
|
font-weight: bold;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
transition: background-color 0.2s ease-in-out, transform 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background-color: #40739e;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:active {
|
button:active {
|
||||||
background-color: #5584ac;
|
transform: scale(0.95);
|
||||||
|
background-color: #0077b6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
@@ -74,27 +84,41 @@ pre {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#code-container {
|
#code-container {
|
||||||
display: flex;
|
margin: 0;
|
||||||
margin: 0 -20px;
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-container .code-line:first-of-type .line-number {
|
||||||
|
padding-top: 10px;
|
||||||
|
border-top-left-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-container .code-line:last-of-type .line-number {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom-left-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-container .code-line:first-of-type #code {
|
||||||
|
padding-top: 10px;
|
||||||
|
border-top-right-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code-container .code-line:last-of-type #code {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom-right-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#code {
|
||||||
|
font-size: 14px;
|
||||||
font-family: 'Fira Code', monospace;
|
font-family: 'Fira Code', monospace;
|
||||||
}
|
|
||||||
|
|
||||||
#document-title {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 14px;
|
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
padding: 0px 11px;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#line-nums {
|
.code-pre {
|
||||||
width: auto;
|
|
||||||
font-size: 14px;
|
|
||||||
padding-left: 11px;
|
|
||||||
padding-top: 13px;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#code-div {
|
#code-div {
|
||||||
@@ -104,13 +128,23 @@ code {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#code {
|
.code-line {
|
||||||
margin-left: 2px;
|
font-family: 'Fira Code', monospace;
|
||||||
padding-bottom: 22px;
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line-number {
|
||||||
|
padding: 0px 11px;
|
||||||
|
user-select: none;
|
||||||
|
background-color: #454545;
|
||||||
|
color: white;
|
||||||
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
#print-area {
|
#print-area {
|
||||||
padding: 20px;
|
padding: 0;
|
||||||
|
padding-top: 20px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +159,10 @@ a {
|
|||||||
-webkit-print-color-adjust: exact;
|
-webkit-print-color-adjust: exact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line-number {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
#document-title {
|
#document-title {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
@@ -133,10 +171,6 @@ a {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#code-container {
|
|
||||||
margin-top: -20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hide-from-print {
|
.hide-from-print {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@@ -161,12 +195,10 @@ p {
|
|||||||
|
|
||||||
::-webkit-scrollbar-track {
|
::-webkit-scrollbar-track {
|
||||||
background: #f1f1f1;
|
background: #f1f1f1;
|
||||||
border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
background: #888;
|
background: #888;
|
||||||
border-radius: 5px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb:hover {
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
|||||||
Reference in New Issue
Block a user