Skip to content

Commit eccd564

Browse files
chore: ci build
1 parent 7843bc3 commit eccd564

File tree

1 file changed

+162
-25
lines changed

1 file changed

+162
-25
lines changed

dist/chatgpt.user.js

Lines changed: 162 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// @name:zh-CN ChatGPT Exporter
44
// @name:zh-TW ChatGPT Exporter
55
// @namespace pionxzh
6-
// @version 2.26.0
6+
// @version 2.27.0
77
// @author pionxzh
88
// @description Easily export the whole ChatGPT conversation history for further analysis or sharing.
99
// @description:zh-CN 轻松导出 ChatGPT 聊天记录,以便进一步分析或分享。
@@ -1201,12 +1201,13 @@ html {
12011201
}
12021202
async function fetchAllConversations() {
12031203
const conversations = [];
1204-
const limit = 20;
1204+
const limit = 100;
12051205
let offset = 0;
12061206
while (true) {
12071207
const result = await fetchConversations(offset, limit);
12081208
conversations.push(...result.items);
12091209
if (offset + limit >= result.total) break;
1210+
if (offset + limit >= 1e3) break;
12101211
offset += limit;
12111212
}
12121213
return conversations;
@@ -1346,7 +1347,7 @@ html {
13461347
};
13471348
}
13481349
function extractConversationResult(conversationMapping, startNodeId) {
1349-
var _a, _b;
1350+
var _a, _b, _c;
13501351
const result = [];
13511352
let currentNodeId = startNodeId;
13521353
while (currentNodeId) {
@@ -1359,7 +1360,7 @@ html {
13591360
}
13601361
if (
13611362
// Skip system messages
1362-
((_a = node2.message) == null ? void 0 : _a.author.role) !== "system" && ((_b = node2.message) == null ? void 0 : _b.content.content_type) !== "model_editable_context"
1363+
((_a = node2.message) == null ? void 0 : _a.author.role) !== "system" && ((_b = node2.message) == null ? void 0 : _b.content.content_type) !== "model_editable_context" && ((_c = node2.message) == null ? void 0 : _c.content.content_type) !== "user_editable_context"
13631364
) {
13641365
result.unshift(node2);
13651366
}
@@ -8732,6 +8733,55 @@ html {
87328733
<script>
87338734
hljs.highlightAll()
87348735
<\/script>
8736+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.3/katex.min.css">
8737+
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.3/katex.min.js"><\/script>
8738+
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.3/contrib/auto-render.min.js"><\/script>
8739+
<script>
8740+
document.addEventListener("DOMContentLoaded", function() {
8741+
renderMathInElement(document.body, {
8742+
delimiters: [
8743+
{ left: "$$", right: "$$", display: true },
8744+
{ left: "$", right: "$", display: false },
8745+
{ left: "\\\\[", right: "\\\\]", display: true },
8746+
{ left: "\\\\(", right: "\\\\)", display: false }
8747+
],
8748+
throwOnError: false,
8749+
ignoredClasses: ["no-katex"],
8750+
preProcess: function(math) {
8751+
return \`\\\\displaystyle \\\\Large \${math}\`;
8752+
}
8753+
});
8754+
document.querySelectorAll('.katex').forEach(function(el) {
8755+
const parent = el.parentNode;
8756+
const grandparent = parent.parentNode;
8757+
if (grandparent.tagName === 'P' && isOnlyContent(grandparent, parent)) {
8758+
el.style.width = '100%';
8759+
el.style.display = 'block';
8760+
el.style.textAlign = 'center';
8761+
parent.style.textAlign = 'center';
8762+
} else {
8763+
el.style.display = 'inline-block';
8764+
el.style.width = 'fit-content';
8765+
}
8766+
});
8767+
function isOnlyContent(parent, element) {
8768+
let onlyKaTeX = true;
8769+
parent.childNodes.forEach(function(child) {
8770+
console.log(child.textContent);
8771+
if (child !== element) {
8772+
if (child.nodeType === Node.TEXT_NODE) {
8773+
if (child.textContent.trim().length > 0) {
8774+
onlyKaTeX = false;
8775+
}
8776+
} else if (child.nodeType === Node.ELEMENT_NODE) {
8777+
onlyKaTeX = false;
8778+
}
8779+
}
8780+
});
8781+
return onlyKaTeX;
8782+
}
8783+
});
8784+
<\/script>
87358785

87368786
<style>
87378787
:root {
@@ -8842,6 +8892,31 @@ html {
88428892
border: 1px solid #e2e8f0;
88438893
}
88448894

8895+
[data-width="narrow"] .width-toggle .expand {
8896+
display: block;
8897+
}
8898+
8899+
[data-width="wide"] .width-toggle .narrow {
8900+
display: block;
8901+
}
8902+
8903+
.width-toggle {
8904+
display: inline-flex;
8905+
justify-content: center;
8906+
align-items: center;
8907+
width: 32px;
8908+
height: 32px;
8909+
border-radius: 4px;
8910+
background-color: #fff;
8911+
border: 1px solid #e2e8f0;
8912+
margin-left: 8px;
8913+
cursor: pointer;
8914+
}
8915+
8916+
.width-toggle svg {
8917+
display: none;
8918+
}
8919+
88458920
.metadata_container {
88468921
display: flex;
88478922
flex-direction: column;
@@ -9065,6 +9140,15 @@ html {
90659140
.conversation {
90669141
margin: 0 auto;
90679142
padding: 1rem;
9143+
max-width: 64rem;
9144+
}
9145+
9146+
[data-width="narrow"] .conversation {
9147+
max-width: 64rem;
9148+
}
9149+
9150+
[data-width="wide"] .conversation {
9151+
max-width: 90%;
90689152
}
90699153

90709154
@media (min-width: 1280px) {
@@ -9185,6 +9269,7 @@ html {
91859269
font-size: 0.8rem;
91869270
color: #acacbe
91879271
}
9272+
91889273
</style>
91899274
</head>
91909275

@@ -9202,10 +9287,18 @@ html {
92029287
<svg class="sun" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>
92039288
<svg class="moon" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
92049289
</button>
9290+
<button class="toggle width-toggle">
9291+
<svg class="expand" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg" style="display: block;">
9292+
<path d="M3 12h18M6 8l-4 4 4 4M18 8l4 4-4 4"></path>
9293+
</svg>
9294+
<svg class="narrow" stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="w-4 h-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg" style="display: none;">
9295+
<path d="M3 12h7M14 12h7M6 16l4-4-4-4M18 16l-4-4 4-4"></path>
9296+
</svg>
9297+
</button>
92059298
</h1>
92069299
<div class="conversation-export">
92079300
<p>Exported by
9208-
<a href="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/pionxzh/chatgpt-exporter">ChatGPT Exporter</a>
9301+
<a href="https://github.com/pionxzh/chatgpt-exporter.git">ChatGPT Exporter</a>
92099302
at {{time}}</p>
92109303
</div>
92119304
{{details}}
@@ -9217,23 +9310,50 @@ html {
92179310

92189311
<script>
92199312
function toggleDarkMode(mode) {
9220-
const html = document.querySelector('html')
9221-
const isDarkMode = html.getAttribute('data-theme') === 'dark'
9222-
const newMode = mode || (isDarkMode ? 'light' : 'dark')
9223-
if (newMode !== 'dark' && newMode !== 'light') return
9224-
html.setAttribute('data-theme', newMode)
9313+
const html = document.querySelector('html');
9314+
const isDarkMode = html.getAttribute('data-theme') === 'dark';
9315+
const newMode = mode || (isDarkMode ? 'light' : 'dark');
9316+
if (newMode !== 'dark' && newMode !== 'light') return;
9317+
html.setAttribute('data-theme', newMode);
92259318

9226-
const url = new URL(window.location)
9227-
url.searchParams.set('theme', newMode)
9228-
window.history.replaceState({}, '', url)
9319+
const url = new URL(window.location);
9320+
url.searchParams.set('theme', newMode);
9321+
window.history.replaceState({}, '', url);
9322+
}
9323+
function toggleWidthMode(mode) {
9324+
const body = document.querySelector('body');
9325+
const widthToggleButton = document.querySelector('.width-toggle');
9326+
const isWide = body.getAttribute('data-width') === 'wide';
9327+
const newWidthMode = mode || (isWide ? 'narrow' : 'wide');
9328+
if (newWidthMode !== 'narrow' && newWidthMode !== 'wide') return;
9329+
body.setAttribute('data-width', newWidthMode);
9330+
9331+
const url = new URL(window.location);
9332+
url.searchParams.set('width', newWidthMode);
9333+
window.history.replaceState({}, '', url);
9334+
9335+
// Update the icon based on the current mode
9336+
const narrowIcon = widthToggleButton.querySelector('.narrow');
9337+
const expandIcon = widthToggleButton.querySelector('.expand');
9338+
9339+
if (newWidthMode === 'wide') {
9340+
expandIcon.style.display = "none";
9341+
narrowIcon.style.display = "block";
9342+
} else {
9343+
expandIcon.style.display = "block";
9344+
narrowIcon.style.display = "none";
9345+
}
92299346
}
92309347

9231-
// Support for ?theme=dark
9232-
const urlParams = new URLSearchParams(window.location.search)
9233-
const theme = urlParams.get('theme')
9234-
if (theme) toggleDarkMode(theme)
9348+
const urlParams = new URLSearchParams(window.location.search);
9349+
const theme = urlParams.get('theme');
9350+
const width = urlParams.get('width');
9351+
9352+
if (theme) toggleDarkMode(theme);
9353+
if (width) toggleWidthMode(width);
92359354

9236-
document.querySelector('.toggle').addEventListener('click', () => toggleDarkMode())
9355+
document.querySelector('.toggle').addEventListener('click', () => toggleDarkMode());
9356+
document.querySelector('.width-toggle').addEventListener('click', () => toggleWidthMode());
92379357
<\/script>
92389358
</body>
92399359

@@ -20522,14 +20642,15 @@ html {
2052220642
level: 9
2052320643
}
2052420644
});
20525-
downloadFile("chatgpt-export.zip", "application/zip", blob);
20645+
downloadFile("chatgpt-export-html.zip", "application/zip", blob);
2052620646
return true;
2052720647
}
2052820648
function conversationToHtml(conversation, avatar, metaList) {
2052920649
const { id, title: title2, model, modelSlug, createTime, updateTime, conversationNodes } = conversation;
2053020650
const enableTimestamp = ScriptStorage.get(KEY_TIMESTAMP_ENABLED) ?? false;
2053120651
const timeStampHtml = ScriptStorage.get(KEY_TIMESTAMP_HTML) ?? false;
2053220652
const timeStamp24H = ScriptStorage.get(KEY_TIMESTAMP_24H) ?? false;
20653+
const LatexRegex2 = /(\s\$\$.+?\$\$\s|\s\$.+?\$\s|\\\[.+?\\\]|\\\(.+?\\\))|(^\$$[\S\s]+?^\$$)|(^\$\$[\S\s]+?^\$\$\$)/gm;
2053320654
const conversationHtml = conversationNodes.map(({ message }) => {
2053420655
var _a, _b, _c, _d;
2053520656
if (!message || !message.content) return null;
@@ -20550,11 +20671,27 @@ html {
2055020671
let postSteps = [];
2055120672
if (message.author.role === "assistant") {
2055220673
postSteps = [...postSteps, (input) => transformFootNotes$2(input, message.metadata)];
20674+
postSteps.push((input) => {
20675+
const matches = input.match(LatexRegex2);
20676+
const isCodeBlock = /```/.test(input);
20677+
if (!isCodeBlock && matches) {
20678+
let index2 = 0;
20679+
input = input.replace(LatexRegex2, () => {
20680+
return `╬${index2++}╬`;
20681+
});
20682+
input = input.replace(/^\\\[(.+)\\\]$/gm, "$$$$$1$$$$").replace(/\\\[/g, "$$").replace(/\\\]/g, "$$").replace(/\\\(/g, "$").replace(/\\\)/g, "$");
20683+
}
20684+
let transformed = toHtml(fromMarkdown(input));
20685+
if (!isCodeBlock && matches) {
20686+
transformed = transformed.replace(/╬(\d+)╬/g, (_24, index2) => {
20687+
return matches[+index2];
20688+
});
20689+
}
20690+
return transformed;
20691+
});
2055320692
}
2055420693
if (message.author.role === "user") {
20555-
postSteps = [...postSteps, (input) => `<p>${escapeHtml(input)}</p>`];
20556-
} else {
20557-
postSteps = [...postSteps, (input) => toHtml(fromMarkdown(input))];
20694+
postSteps = [...postSteps, (input) => `<p class="no-katex">${escapeHtml(input)}</p>`];
2055820695
}
2055920696
const postProcess = (input) => postSteps.reduce((acc, fn2) => fn2(acc), input);
2056020697
const content2 = transformContent$2(message.content, message.metadata, postProcess);
@@ -20661,7 +20798,7 @@ ${content2.text}
2066120798
}).join("\n")) || "";
2066220799
}
2066320800
default:
20664-
return postProcess("[Unsupported Content]");
20801+
return postProcess(`[Unsupported Content: ${content2.content_type} ]`);
2066520802
}
2066620803
}
2066720804
function escapeHtml(html2) {
@@ -20978,7 +21115,7 @@ ${content2.text}
2097821115
level: 9
2097921116
}
2098021117
});
20981-
downloadFile("chatgpt-export.zip", "application/zip", blob);
21118+
downloadFile("chatgpt-export-json.zip", "application/zip", blob);
2098221119
return true;
2098321120
}
2098421121
function conversationToJson(conversation) {
@@ -21025,7 +21162,7 @@ ${content2.text}
2102521162
level: 9
2102621163
}
2102721164
});
21028-
downloadFile("chatgpt-export.zip", "application/zip", blob);
21165+
downloadFile("chatgpt-export-markdown.zip", "application/zip", blob);
2102921166
return true;
2103021167
}
2103121168
const LatexRegex$1 = /(\s\$\$.+\$\$\s|\s\$.+\$\s|\\\[.+\\\]|\\\(.+\\\))|(^\$$[\S\s]+^\$$)|(^\$\$[\S\s]+^\$\$$)/gm;

0 commit comments

Comments
 (0)