PageSourceSearch

https://smartstudi.com/scripts/summarizertab.js

js smartstudi.com collected 2026-09-29 04:57:01 UTC 31,812 bytes, 633 lines download raw bytes

1//<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
2//<> THIS FILE CONTAINS JAVASCRIPT FOR THE WEBSITE'S SUMMARIZE TAB                               <>
3//<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
4
5// retrieve all necessary elements
6const inputParagraphsTextBox = document.getElementById('summarizer-input-paragraphs');
7const inputParagraphsContainer = document.getElementsByClassName('summarizer-input-paragraphs-container')[0]
8const outputParagraphsTextBox = document.getElementById('summarizer-output-paragraphs');
9const outputParagraphsContainer = document.getElementsByClassName('summarizer-output-paragraphs-container')[0]
10const summarizeButton = document.getElementById('summarizer-summarize-button');
11const loadingImg = document.getElementById('summarizer-loading-img');
12const writeToDocContainer = document.getElementById('summarizer-write-to-doc-container');
13
14
15(async () => {
16  // Call the function to generate the UI
17  await createAllSelectInputOptions(
18      "summarizer-all-select-input-options", // ID for the overall container
19      "Or Summarize From:", // Header text content
20    "Summarize Google Docs, Google Slides, Google Drawings, .pdf, .docx, .pptx, .png, .jpg, and .heic!",//"Summarize Google Docs, Google Slides, Google Drawings, YouTube video transcripts, .pdf, .docx, .pptx, .png, .jpg, and .heic!", // Description below the buttons
21      "summarizer-from-device-input", // ID for the "From Device" button
22      {
23          id: "summarizer-from-google-drive-input", // ID for the "From Google Drive" button
24          action: "extractGoogleFileContent",
25          writeToGoogleFileContentId: null,
26      },
27      null,//"summarizer-from-youtube-input", // ID for the "From YouTube" button
28      "summarizer-input-paragraphs-container", // ID of the parent container where everything will be appended
29      "summarizer-input-paragraphs", // ID of the text area for written content (above the buttons)
30      "summarizer-image-container", // ID of the image container (for image previews)
31      ["google-doc", "google-slide", "google-drawing", "pdf", "pptx", "docx", "png", "jpg", "jpeg", "heic", "heif", "heif-sequence"], // what files can be accessed to extract content (these are all possible file types)
32    );
33
34    if (chromeExtensionFormatting != 'true') {
35        // add a Write to Doc button
36        await createFromGoogleDrive(
37            'summarizer-write-to-doc-input',
38            'summarizer-write-to-doc-container',
39            googleApiKey,
40            'writeToGoogleFile',
41            'summarizer-output-paragraphs',
42            "summarizer-input-paragraphs", // ID of the text area for written content (above the buttons)
43            "summarizer-image-container", // ID of the image container (for image previews)
44            ["google-doc", "docx"]
45            
46        )
47        const writeToDocButton = document.getElementById('summarizer-write-to-doc-input')
48    }
49
50    createWordCounter(
51        'summarizer-wordcounter',
52        40000,
53        'summarizer-input-paragraphs'
54    );
55})();
56
57
58
59// add formatting rules to outputParagraphsTextBox
60outputParagraphsTextBox.addEventListener('input', function (event) {
61    outputParagraphsTextBox.value = formatAllBulletPoints(outputParagraphsTextBox.value, outputParagraphsTextBox.offsetWidth)
62});
63function formatAllBulletPoints(text, textareaWidth) {
64    function extractBulletPoints(text) {
65        const bulletPoints = [];
66        const segments = text.split("⬤ ").slice(1); // Split by "⬤ " and ignore the first empty segment
67    
68        segments.forEach(segment => {
69            // Trim each segment and remove any trailing newline characters
70            const bulletPoint = segment.split("\n")[0].trim();
71            if (bulletPoint) bulletPoints.push(bulletPoint);
72        });
73    
74        return bulletPoints;
75    }
76
77    const bulletPointsArray = extractBulletPoints(text)
78
79
80    for (let i = 0; i < bulletPointsArray.length; i++) {
81        const originalBullet = bulletPointsArray[i];
82        const newIndentedBullet = indentBulletPoint(bulletPointsArray[i], textareaWidth);
83        
84        // Replace all instances of the original bullet point with the indented version
85        text = text.replace(originalBullet, newIndentedBullet);
86    }
87
88    return text;
89
90    
91}
92function indentBulletPoint(text, textareaWidth) {
93        let wordsPerLine = 5;
94        if (textareaWidth > 900) {
95            wordsPerLine = 10;
96        } else if (textareaWidth > 800) {
97            wordsPerLine = 10;
98        } else if (textareaWidth > 700) {
99            wordsPerLine = 10;
100        } else if (textareaWidth > 650) {
101            wordsPerLine = 10;
102        } else if (textareaWidth > 600) {
103            wordsPerLine = 7;
104        } else if (textareaWidth > 550) {
105            wordsPerLine = 6;
106        } else if (textareaWidth > 500) {
107            wordsPerLine = 5;
108        } else if (textareaWidth > 450) {
109            wordsPerLine = 5;
110
111        }
112        // remove all redundant whitespace and newlines
113        text = text.replace(/\n/g, " ").replace(/\s{2,}/g, " ");
114
115        // Split the text into an array of words
116        const words = text.split(" ");
117        
118        // Initialize an array to store 5-word segments
119        let segments = [];
120        
121        // Loop to group words into 5-word segments
122        for (let i = 0; i < words.length;
122 i += wordsPerLine) {
123            segments.push(words.slice(i, i + wordsPerLine).join(" "));
124        }
125        
126        // Add "\n     " to the beginning of each segment except the first
127        return segments.map((segment, index) => index === 0 ? segment : `\n     ${segment}`).join(" ");
128    }
129
130// create "How Do You Want to Summarize:" settings
131const summarizerSettingsHeader =  document.createElement('div')
132summarizerSettingsHeader.textContent = 'How do you want to summarize:'
133summarizerSettingsHeader.className = 'language-text-content'
134summarizerSettingsHeader.id = 'summarizer-settings-header'
135summarizerSettingsHeader.style.fontWeight = 'bold';
136summarizerSettingsHeader.style.marginBottom = '30px'
137outputParagraphsContainer.appendChild(summarizerSettingsHeader)
138
139// function to create dropdown
140function createDropdown(description, optionsArray, dropdownButtonId, selectOptionCallback = ()=>{}){
141
142    const dropdownContainer = document.createElement('div')
143    dropdownContainer.className = 'summarizer-dropdown'
144    dropdownContainer.style.marginBottom = '15px'
145    outputParagraphsContainer.appendChild(dropdownContainer)
146
147    const dropdownDescription = document.createElement('div')
148    dropdownDescription.className = 'summarizer-settings-description language-text-content'
149    dropdownDescription.style.display = 'inline-block'
150    dropdownDescription.textContent = description
151    dropdownContainer.appendChild(dropdownDescription)
152
153    const dropdownSelectionContainer = document.createElement('div')
154    dropdownSelectionContainer.style.display = 'inline-block'
155    dropdownContainer.appendChild(dropdownSelectionContainer)
156
157    const dropdownButton = document.createElement('button')
158    dropdownButton.className = 'summarizer-dropdown-btn'
159    dropdownButton.style.padding = '10px 10px'
160    dropdownButton.id = dropdownButtonId
161    if (optionsArray[0].length > 15) {
162        dropdownButton.style.width = '230px'
163    }
164    dropdownButton.style.textAlign = 'center'
165    dropdownButton.textContent = optionsArray[0]
166    dropdownSelectionContainer.appendChild(dropdownButton)
167
168    const arrowImg = document.createElement('img')
169    arrowImg.className = 'summarizer-arrow'
170    arrowImg.src = '/images/arrowDownGrey.png'
171    arrowImg.width = '17'
172    arrowImg.width  = '17'
173    arrowImg.style.display = 'inline-block'
174    dropdownButton.appendChild(arrowImg)
175
176    const dropdownContent = document.createElement('div')
177    dropdownContent.style.display = 'none'
178    dropdownContent.className = 'summarizer-dropdown-content'
179    dropdownSelectionContainer.appendChild(dropdownContent)
180
181    // Function to handle the selection of an option
182    function selectAIContentDetectorOption(optionText) {
183        // Update the button text with the selected option
184        dropdownButton.innerHTML = optionText;
185        if (optionText.length > 15) {
186            dropdownButton.style.width = '230px'
187        } else {
188            dropdownButton.style.width = '200px'
189        }
190        dropdownButton.appendChild(arrowImg);  // Add the arrow back to the button
191        arrowImg.src = '/images/arrowDownGrey.png';  // Reset the arrow
192        dropdownContent.style.display = 'none';  // Close the dropdown
193
194        // call the callback
195        selectOptionCallback()
196    }
197    
198    for (const option in optionsArray) {
199        const dropdownOption = document.createElement('a')
200        dropdownOption.href = '#'
201        dropdownOption.id = `summarizer-dropdown-option-${option.replace(/\s+/g, '_')}`
202        dropdownOption.textContent = optionsArray[option]
203        // Add event listeners to the dropdown options
204        dropdownOption.addEventListener('click', function(event) {
205            event.preventDefault(); // Prevent default link behavior
206            selectAIContentDetectorOption(optionsArray[option]);
207
208        });
209        dropdownContent.appendChild(dropdownOption)
210    }
211    
212    // Toggle dropdown and arrow on button click (including arrow)
213    dropdownButton.addEventListener('click', function(event) {
214        // Prevent default behavior if clicking on the arrow
215        event.stopPropagation();
216    
217        // Toggle dropdown visibility
218        dropdownContent.style.display = dropdownContent.style.display === 'block' ? 'none' : 'block';
219    
220        // Toggle the arrow direction
221        if (dropdownContent.style.display === 'block') {
222            arrowImg.src = '/images/arrowUpGrey.png';
223        } else {
224            arrowImg.src = '/images/arrowDownGrey.png';
225        }
226    });
227
228
229    // Close the dropdown if the user clicks outside of it
230    window.addEventListener('click', function(event) {
231        if (!dropdownButton.contains(event.target)) {
232            dropdownContent.style.display = 'none';
233            arrowImg.src = '/images/arrowDownGrey.png';  // Reset the arrow to down
234        }
235    });
236}
237// create summarize by
238createDropdown(
239    'Summarize by:',
240    [
241        "Key concepts",  
242        "Thesis statement focus", 
243        "Chapter", 
244        "Section", 
245        "Sub-section", 
246        "Header", 
247        "Sub-header",
248        "Slide"
249    ],
250    'summarizer-summarize-by-dropdown',
251    ()=>{
252        if (document.getElementById('summarizer-summarize-by-dropdown').textContent === "Thesis statement focus"){
253            typeThesisContainer.style.display = 'block'
254        } else {
255            typeThesisContainer.style.display = 'none'
256        }
257    }
258)
259
260const typeThesisContainer = document.createElement('div')
261typeThesisContainer.style.marginBottom = '15px'
262typeThesisContainer.style.display = 'none'
263outputParagraphsContainer.appendChild(typeThesisContainer)
264const typeThesisDescription = document.createElement('div')
265typeThesisDescription.className = 'summarizer-settings-description language-text-content'
266typeThesisDescription.textContent = "Your thesis:"
267typeThesisContainer.appendChild(typeThesisDescription)
268const typeThesisTextbox = document.createElement('textarea')
269typeThesisTextbox.placeholder = 'Up to 200 words'
270typeThesisTextbox.id = 'summarizer-type-thesis-textbox'
271typeThesisTextbox.className = 'summarizer-settings-textbox'
272typeThesisContainer.appendChild(typeThesisTextbox)
273
274const summaryLengthContainer = document.createElement('div')
275summaryLengthContainer.style.marginBottom = '15px'
276outputParagraphsContainer.appendChild(summaryLengthContainer)
277const summaryLengthDescription1 = document.createElement('span')
278summaryLengthDescription1.className = 'summarizer-settings-description language-text-content'
279summaryLengthDescription1.textContent = "Summary is"
280summaryLengthContainer.appendChild(summaryLengthDescription1)
281const summaryLengthInput = document.createElement("input");
282summaryLengthInput.style.display = 'inline-block'
283summaryLengthInput.style.marginLeft = '6px'
284summaryLengthInput.style.marginRight = '6px'
285summaryLengthInput.className = 'summarizer-settings-number-input'
286summaryLengthInput.id = 'summarizer-summary-length-input'
287summaryLengthInput.type = "number";
288summaryLengthInput.value = 100;
289summaryLengthInput.min = 30;
290inputParagraphsTextBox.addEventListener('input', ()=>{
291    const wordCountInInputParagraphsTextBox = getWordCount(truncateAfterWords(inputParagraphsTextBox.value, 39990))
292    if (wordCountInInputParagraphsTextBox < 400){
293        summaryLengthInput.max = 400
294    } else {
295        summaryLengthInput.max = (Math.floor((wordCountInInputParagraphsTextBox/400)*100) < 400 ? 400 : Math.floor((wordCountInInputParagraphsTextBox/400)*30))
296    }
297})
298summaryLengthContainer.appendChild(summaryLengthInput)
299const summaryLengthDescription2 = document.createElement('span')
300summaryLengthDescription2.className = 'summarizer-settings-description language-text-content'
301summaryLengthDescription2.textContent = "words long"
302summaryLengthContainer.appendChild(summaryLengthDescription2)
303
304// function to create dropdown
305function createCheckbox(description, checkboxId, checked, checkedCallback = ()=>{}){
306
307    const checkboxContainer = document.createElement('div')
308    checkboxContainer.className = 'summarizer-checkbox'
309    checkboxContainer.style.marginBottom = '15px'
310    outputParagraphsContainer.appendChild(checkboxContainer)
311
312    const checkbox = document.createElement("input");
313    checkbox.style.verticalAlign = 'middle'
314    checkbox.type = "checkbox";
315    checkbox.style.width = '20px';  // Adjust the width as needed
316    checkbox.style.height = '20px';
317    checkbox.id = checkboxId
318    checkbox.checked = checked
319    checkbox.style.marginRight = '6px'
320
321    checkbox.style.display = 'inline-block';
322    checkbox.addEventListener('change', ()=>{
323        checkedCallback()
324    })
325    checkboxContainer.appendChild(checkbox)
326
327    const checkboxDescription = document.createElement('div')
328    checkboxDescription.className = 'summarizer-settings-description language-text-content'
329    checkboxDescription.style.display = 'inline-block'
330    checkboxDescription.style.verticalAlign = 'middle'
331    checkboxDescription.textContent = description
332    checkboxContainer.appendChild(checkboxDescription)
333
334}
335
336createCheckbox(
337    "Include quotes",
338    "summarizer-include-quotes-checkbox",
339    true
340)
341
342createCheckbox(
343    "In paragraphs",
344    "summarizer-in-paragraphs-checkbox",
345    true,
346    ()=>{
347        if (document.getElementById('summarizer-in-paragraphs-checkbox').checked) {
348            inParagraphsContainer.style.display = 'block'
349            document.getElementById('summarizer-in-bullet-points-checkbox').checked = false
350            inBulletPointsContainer.style.display = 'none'
351        } else {
352            inParagraphsContainer.style.display = 'none'
353            document.getElementById('summarizer-in-bullet-points-checkbox').checked = true
354            inBulletPointsContainer.style.display = 'block'
355        }
356    }
357)
358
359const inParagraphsContainer = document.createElement('div')
360//inParagraphsContainer.style.display = 'none'
361inParagraphsContainer.style.marginBottom = '15px'
362outputParagraphsContainer.appendChild(inParagraphsContainer)
363const inParagraphsInput = document.createElement("input");
364inParagraphsInput.style.display = 'inline-block'
365inParagraphsInput.style.marginLeft = '25px'
366inParagraphsInput.style.marginRight = '6px'
367inParagraphsInput.className = 'summarizer-settings-number-input'
368inParagraphsInput.id = 'summarizer-in-paragraphs-input'
369inParagraphsInput.style.width = '40px'
370inParagraphsInput.type = "number";
371inParagraphsInput.value = 5;
372inParagraphsInput.min = 1;
373inParagraphsInput.max = 100
374inParagraphsContainer.appendChild(inParagraphsInput)
375const inParagraphsDescription = document.createElement('span')
376inParagraphsDescription.className = 'summarizer-settings-description language-text-content'
377inParagraphsDescription.textContent = "Paragraphs"
378inParagraphsContainer.appendChild(inParagraphsDescription)
379
380createCheckbox(
381    "In bullet points",
382    "summarizer-in-bullet-points-checkbox",
383    false,
384    ()=>{
385        if (document.getElementById('summarizer-in-bullet-points-checkbox').checked) {
386            inBulletPointsContainer.style.display = 'block'
387            document.getElementById('summarizer-in-paragraphs-checkbox').checked = false
388            inParagraphsContainer.style.display = 'none'
389        } else {
390            inBulletPointsContainer.style.display = 'none'
391            document.getElementById('summarizer-in-paragraphs-checkbox').checked = true
392            inParagraphsContainer.style.display = 'block'
393        }
394    }
395)
396
397const inBulletPointsContainer = document.createElement('div')
398inBulletPointsContainer.style.display = 'none'
399inBulletPointsContainer.style.marginBottom = '15px'
400outputParagraphsContainer.appendChild(inBulletPointsContainer)
401const inBulletPointsInput = document.createElement("input");
402inBulletPointsInput.style.display = 'inline-block'
403inBulletPointsInput.style.marginLeft = '25px'
404inBulletPointsInput.style.marginRight = '6px'
405inBulletPointsInput.className = 'summarizer-settings-number-input'
406inBulletPointsInput.id = 'summarizer-in-bullet-points-input'
407inBulletPointsInput.style.width = '40px'
408inBulletPointsInput.type = "number";
409inBulletPointsInput.value = 5;
410inBulletPointsInput.min = 1;
411inBulletPointsInput.max = 100
412inBulletPointsContainer.appendChild(inBulletPointsInput)
413const inBulletPointsDescription = document.createElement('span')
414inBulletPointsDescription.className = 'summarizer-settings-description language-text-content'
415inBulletPointsDescription.textContent = "Bullet points"
416inBulletPointsContainer.appendChild(inBulletPointsDescription)
417
418createCheckbox(
419    "Additional requirements:",
420    "summarizer-focus-on-checkbox",
421    false
422)
423
424const additionalRequirementsTextbox = document.createElement('textarea')
425additionalRequirementsTextbox.style.display = 'block'
426//additionalRequirementsTextbox.style.marginTop = '-10px'
427additionalRequirementsTextbox.style.marginLeft = '25px'
428additionalRequirementsTextbox.style.width = '300px'
429additionalRequirementsTextbox.style.marginBottom = '15px'
430additionalRequirementsTextbox.placeholder = 'Up to 200 words'
431additionalRequirementsTextbox.id = 'summarizer-focus-on-textbox'
432additionalRequirementsTextbox.className = 'summarizer-settings-textbox'
433outputParagraphsContainer.appendChild(additionalRequirementsTextbox)
434
435
436function toSansSerifBoldFont(input) {
437    const normal = [
438      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
439      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
440      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
441    ];
442  
443    const sansSerifBold = [
444      '𝗔', '𝗕', '𝗖', '𝗗', '𝗘', '𝗙', '𝗚', '𝗛', '𝗜', '𝗝', '𝗞', '𝗟', '𝗠', '𝗡', '𝗢', '𝗣', '𝗤', '𝗥', '𝗦', '𝗧', '𝗨', '𝗩', '𝗪', '𝗫', '𝗬', '𝗭',
445      '𝗮', '𝗯', '𝗰', '𝗱', '𝗲', '𝗳', '𝗴', '𝗵', '𝗶', '𝗷', '𝗸', '𝗹', '𝗺', '𝗻', '𝗼', '𝗽', '𝗾', '𝗿', '𝘀', '𝘁', '𝘂', '𝘃', '𝘄', '𝘅', '𝘆', '𝘇',
446      '𝟬', '𝟭', '𝟮', '𝟯', '𝟰', '𝟱', '𝟲', '𝟳', '𝟴', '𝟵'
447    ];
448  
449    const specialMap = {};
450    normal.forEach((char, index) => {
451      specialMap[char] = sansSerifBold[index];
452    });
453  
454    let result = "";
455    for (let char of input) {
456      result += specialMap[char] || char;
457    }
458  
459    return result;
460  }
461  
462function replaceBracketedTextWithBold(inputString) {
463// Find all text within brackets
464const matches = inputString.match(/\[([^\]]+)\]/g);
465
466if (matches) {
467    matches.forEach(match => {
468    // Remove brackets and convert text inside brackets
469    const textInsideBrackets = match.slice(1, -1);
470    const boldText = toSansSerifBoldFont(textInsideBrackets);
471
472    // Replace the original [text] with the bolded text
473    inputString = inputString.replace(match, boldText);
474    });
475}
476
477return inputString;
478}
479
480let useStoredContent = false;
481let textareaConfig = {update: true}
482// add event listener to summarize button
483summarizeButton.addEventListener('click', async ()=> {
484    textareaConfig.update = false
485    summarizeButton.disabled = true
486    loadingImg.style.display = 'inline-block'
487    try {
488        // format the inputted text and get it ready for summarizing
489        if ((getWordCount(inputParagraphsTextBox.value) > 40000 && document.getElementById('summarizer-input-paragraphs').style.display != "none") ||getWordCount(inputParagraphsTextBox.value) < minInputWords ) {
490            showMessage((getWordCount(inputParagraphsTextBox.value) > 40000 ? `<span class="language-text-content">Your text is over 40000 words. Please use a shorter text</span>` : `<span class="language-text-content">Your text is less than ${minInputWords} words</span>`))
491        } else if (getWordCount(typeThesisTextbox.value) > 200 && document.getElementById('summarizer-summarize-by-dropdown').textContent.trim() === "Thesis statement focus") {
492            showMessage(`<span class="language-text-content">Your thesis statement cannot be over 200 words</span>`)
493        } else if (getWordCount(additionalRequirementsTextbox.value) > 200) {
494            showMessage(`<span class="language-text-content">Additional requirements cannot be over 200 words</span>`)
495        } else {
496
497            const inputParagraphsText = inputParagraphsTextBox.value
498            const summarizeBy = document.getElementById('summarizer-summarize-by-dropdown').textContent.trim()
499            const thesisStatement = typeThesisTextbox.value
500            const summaryLength = summaryLengthInput.value
501            const includeQuotes = (document.getElementById('summarizer-include-quotes-checkbox').checked ? "true" : "false")
502            const additionalRequirements = (document.getElementById('summarizer-focus-on-checkbox').checked ? "true" : "false")
503            const whatAdditionalRequirements = additionalRequirementsTextbox.value
504            const inBulletPoints = (document.getElementById('summarizer-in-bullet-points-checkbox').checked ? "true" : "false")
505            const howManyBulletPoints = inBulletPointsInput.value
506            const inParagraphs = (document.getElementById('summarizer-in-paragraphs-checkbox').checked ? "true" : "false")
507            const howManyParagraphs = inParagraphsInput.value
508
509            // make sure all proper fields have the sufficient amount of words
510            if (summarizeBy === "Thesis statement focus" && !thesisStatement) {
511                showMessage(`<span class="language-text-content">Your thesis statement is empty</span>`)
512            } else if (additionalRequirements === "true" && !whatAdditionalRequirements) {
513                showMessage(`<span class="language-text-content">Please include what your additional requirements in the summary settings</span>`)
514            } else {
515                let response;
516                if (!useStoredContent) {
517
518                    // clear actions and storedContent textarea event listeners
519                    storedContentClearActions("summarizertab.js", storedContent)
520
521                    // add the actions
522                    storedContentAddActions("summarizertab.js", storedContent, 
523                        [
524                            {actionId: "summarizer-set-summarizer-input-paragraphs", type: "setTextareaValue", textareaId: "summarizer-input-paragraphs", value: inputParagraphsTextBox.value, image: null, data: summarizeBy, dispatchEvent: "input"},
525                            {actionId: "summarizer-set-summarizer-type-thesis-textbox", type: "setTextareaValue", textareaId: "summarizer-type-thesis-textbox", value: typeThesisTextbox.value, image: null},
526                            {actionId: "summarizer-set-summarizer-summary-length-input", type: "setTextareaValue", textareaId: "summarizer-summary-length-input", value: summaryLengthInput.value, image: null},
527                            {actionId: "summarizer-change-checkbox-summarizer-include-quotes-checkbox", type: "changeCheckbox", checkboxId: "summarizer-include-quotes-checkbox", value: includeQuotes === "true", dispatchEvent: "change"},
528                            {actionId: "summarizer-change-checkbox-summarizer-focus-on-checkbox", type: "changeCheckbox", checkboxId: "summarizer-focus-on-checkbox", value: additionalRequirements === "true", dispatchEvent: "change"},
529                            {actionId: "summarizer-set-summarizer-focus-on-textbox", type: "setTextareaValue", textareaId: "summarizer-focus-on-textbox", value: additionalRequirementsTextbox.value, image: null},
530                            {actionId: "summarizer-change-checkbox-summarizer-in-bullet-points-checkbox", type: "changeCheckbox", checkboxId: "summarizer-in-bullet-points-checkbox", value: inBulletPoints === "true", dispatchEvent: "change"},
531                            {actionId: "summarizer-set-summarizer-in-bullet-points-input", type: "setTextareaValue", textareaId: "summarizer-in-bullet-points-input", value: inBulletPointsInput.value, image: null},
532                            {actionId: "summarizer-change-checkbox-summarizer-in-paragraphs-checkbox", type: "changeCheckbox", checkboxId: "summarizer-in-paragraphs-checkbox", value: inParagraphs === "true", dispatchEvent: "change"},
533                            {actionId: "summarizer-set-summarizer-in-paragraphs-input", type: "setTextareaValue", textareaId: "summarizer-in-paragraphs-input", value: inParagraphsInput.value, image: null},
534                        ]
535                    )
536                    
537                    response = await getServerResponse(`${httpOrHttps}://${domainName}/summarizer/create-summary`,
538                        JSON.stringify({
539                            "userInfo": userInfo,
540                            "inputParagraphsText" : truncateAfterWords(inputParagraphsText, 39990),
541                            "summarizeBy": summarizeBy,
542                            "thesisStatement": thesisStatement,
543                            "summaryLength" : summaryLength,
544                            "includeQuotes" : includeQuotes,
545                            "additionalRequirements" : additionalRequirements,
546                            "whatAdditionalRequirements" : whatAdditionalRequirements,
547                            "inBulletPoints": inBulletPoints,
548                            "howManyBulletPoints": howManyBulletPoints,
549                            "inParagraphs" : inParagraphs,
550                            "howManyParagraphs" : howManyParagraphs,
551                            "sidebarChromeExtension":  chromeExtensionFormatting === 'true'
552                        })
553                    )
554
555                    // add the actions
556                    storedContentAddActions("summarizertab.js", storedContent, 
557                        [
558                            {actionId: "summarizer-click-summarize-button", type: "clickElement", elementId: "summarizer-summarize-button", elementClassName: null, data: response.canUse, textareaId: "summarizer-output-paragraphs", value: ""},
559                        ]
560                    )
561                    
562                } else {
563                    document.getElementById('summarizer-summarize-by-dropdown').textContent = retrieveDataFromStoredContent("summarizertab.js", "summarizer-set-summarizer-input-paragraphs");
564                    if (document.getElementById('summarizer-summarize-by-dropdown').textContent === "Thesis statement focus"){
565                        typeThesisContainer.style.display = 'block'
566                    } else {
567                        typeThesisContainer.style.display = 'none'
568                    }
569                    response = { 
570                        canUse: retrieveDataFromStoredContent("summarizertab.js", "summarizer-click-summarize-button", true), 
571                        summary: retrieveKeyDataFromStoredContent("summarizertab.js", "summarizer-click-summarize-button", "value")
572                    }
573                    //console.log("useStoredContent response:", response)
574                }
575
576                updateStoredContentTextareaValues("summarizertab.js",
577                    [
578                        {actionId: "summarizer-set-summarizer-input-paragraphs", max: 40000, min: 60},
579                        {actionId: "summarizer-set-summarizer-type-thesis-textbox", max: 200, min: 5},
580                        {actionId: "summarizer-set-summarizer-summary-length-input", max: 4000},
581                        {actionId: "summarizer-set-summarizer-focus-on-textbox", max: 200, min: 5},
582                        {actionId: "summarizer-set-summarizer-in-bullet-points-input", max: 100},
583                        {actionId: "summarizer-set-summarizer-in-paragraphs-input", max: 100},
584                    ],
585                    textareaConfig
586                )
587
588                if (response.canUse === "true") {
589
590                    if (!useStoredContent) {
591                        outputParagraphsTextBox.value = replaceBracketedTextWithBold(formatAllBulletPoints(response.summary, outputParagraphsTextBox.offsetWidth))                        
592                    } else {
593                        outputParagraphsTextBox.value = response.summary                        
594                    }
595                    writeToDocContainer.style.display = 'inline-block'
596
597                    if (!useStoredContent) {
598                        // add the actions
599                        storedContentAddActions("summarizertab.js", storedContent, 
600                            [
601                                {actionId: "summarizer-click-summarize-button", type: "clickElement", elementId: "summarizer-summarize-button", elementClassName: null, data: response.canUse, textareaId: "summarizer-output-paragraphs", value: outputParagraphsTextBox.value},
602                            ]
603                        )
604                    }
605
606                    updateStoredContentTextareaValues("summarizertab.js",
607                        [
608                            {actionId: "summarizer-click-summarize-button", limit: 40000}
609                        ],
610                        textareaConfig
611                    )
612
613                } else {
614                    showMessage(null, null, response.canUse)
615                }
616                if (!useStoredContent) {
617                    await setStoredContent()
618                }
619            }
620        }
621
622    } catch (error) {
623        console.log(error)
624        showMessage(`<span class="language-text-content">An error occured while summarizing your text. Please try again.</span>`)
625    }
626    textareaConfig.update = true
627    summarizeButton.disabled = false
628    loadingImg.style.display = 'none'
629})
630
631useStoredContent = true
632try {await storedContentExecuteActions("summarizertab.js", globalThis);} catch (e) {console.error(e)}
633useStoredContent = false

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.