diff --git a/content.js b/content.js
index 771ef44..cf046a6 100644
--- a/content.js
+++ b/content.js
@@ -567,6 +567,13 @@
analyzeBtn.disabled = true;
try {
+ if (tab === 'qa') {
+ const freshData = extractApplicationQuestions();
+ if (freshData.length > 0) {
+ jobData.questions = freshData;
+ }
+ }
+
const prompt = buildPromptV2(tab, jobData, settings.userProfile, settings.language);
const response = await chrome.runtime.sendMessage({
type: 'GEMINI_REQUEST',
@@ -749,6 +756,25 @@ Brief honest assessment of this opportunity for my profile`
// ─── Markdown Renderer ───────────────────────────────────────────────────
function renderMarkdown(text) {
+ try {
+ const startIdx = text.indexOf('{');
+ const endIdx = text.lastIndexOf('}');
+ if (startIdx !== -1 && endIdx !== -1) {
+ const parsed = JSON.parse(text.substring(startIdx, endIdx + 1));
+ let html = '
';
+ for (const [q, a] of Object.entries(parsed)) {
+ html += `
`;
+ }
+ html += '
';
+ return html;
+ }
+ } catch(e) {
+ // Not JSON, continue to normal markdown rendering
+ }
+
return text
.replace(/&/g, '&').replace(//g, '>')
.replace(/^## (.+)$/gm, '$1
')
@@ -766,25 +792,77 @@ Brief honest assessment of this opportunity for my profile`
function autoFillAnswers(qaText, root) {
showPanelToast(root, '🔄 Attempting to fill answers...');
- // Parse numbered answers from AI response
- const answerLines = qaText.split('\n');
- const inputs = document.querySelectorAll('.jobs-easy-apply-content input[type="text"], .jobs-easy-apply-content textarea');
+ let answers = {};
+ try {
+ const startIndex = qaText.indexOf('{');
+ const endIndex = qaText.lastIndexOf('}');
+ if (startIndex !== -1 && endIndex !== -1) {
+ answers = JSON.parse(qaText.substring(startIndex, endIndex + 1));
+ }
+ } catch (e) {
+ console.error('Failed to parse AI answers JSON:', e);
+ }
+
+ if (Object.keys(answers).length === 0) {
+ showPanelToast(root, '⚠️ Could not parse answers. Please copy manually.');
+ return;
+ }
let filled = 0;
- inputs.forEach((input, idx) => {
- const answerLine = answerLines.find(l => l.match(new RegExp(`^${idx + 1}\\.`)));
- if (answerLine) {
- const answer = answerLine.replace(/^\d+\.\s*/, '').trim();
- if (answer) {
- input.value = answer;
+ const labels = document.querySelectorAll('.jobs-easy-apply-content label, .jobs-easy-apply-content legend, .jobs-easy-apply-content .fb-dash-form-element__label');
+
+ labels.forEach(label => {
+ const qText = label.textContent.trim().toLowerCase();
+ if (!qText) return;
+
+ const matchedKey = Object.keys(answers).find(k => {
+ const kLower = k.toLowerCase();
+ return kLower.includes(qText) || qText.includes(kLower);
+ });
+
+ if (matchedKey && answers[matchedKey]) {
+ const parent = label.closest('.fb-dash-form-element') || label.parentElement;
+ const answerVal = String(answers[matchedKey]);
+
+ // 1. Fill Text inputs / Textareas
+ const input = parent.querySelector('input[type="text"], textarea');
+ if (input) {
+ input.value = answerVal;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
filled++;
}
+
+ // 2. Select dropdowns
+ const select = parent.querySelector('select');
+ if (select) {
+ const options = Array.from(select.options);
+ const matchedOpt = options.find(o => o.text.toLowerCase() === answerVal.toLowerCase() || o.value.toLowerCase() === answerVal.toLowerCase() || o.text.toLowerCase().includes(answerVal.toLowerCase()));
+ if (matchedOpt) {
+ select.value = matchedOpt.value;
+ select.dispatchEvent(new Event('change', { bubbles: true }));
+ filled++;
+ }
+ }
+
+ // 3. Radio Buttons (Yes/No)
+ const radios = parent.querySelectorAll('input[type="radio"]');
+ if (radios.length > 0) {
+ let radioClicked = false;
+ radios.forEach(radio => {
+ const radioLabel = radio.parentElement.textContent.trim().toLowerCase();
+ const aLower = answerVal.toLowerCase();
+ if (radioLabel === aLower || (aLower === 'yes' && radioLabel.includes('yes')) || (aLower === 'no' && radioLabel.includes('no'))) {
+ radio.click();
+ radioClicked = true;
+ }
+ });
+ if (radioClicked) filled++;
+ }
}
});
- showPanelToast(root, filled > 0 ? `✅ Filled ${filled} fields` : '⚠️ Could not auto-fill. Copy answers manually.');
+ showPanelToast(root, filled > 0 ? `✅ Filled ${filled} fields` : '⚠️ No matching fields found to auto-fill.');
}
// ─── Utilities ───────────────────────────────────────────────────────────
diff --git a/prompts.js b/prompts.js
index 97167ba..c78dafc 100644
--- a/prompts.js
+++ b/prompts.js
@@ -112,47 +112,28 @@ Respond EXACTLY:
## NEW BULLET POINTS TO ADD
- [2-3 new achievement bullets ready to paste into CV — in English]`;
- P.qa = `You are a career coach. Generate ready-to-paste application answers.
-IMPORTANT: ALL answers MUST be in English regardless of the job posting language.
+ const dynamicQuestions = job.questions && job.questions.length > 0
+ ? 'Answer THESE specific application questions:\n' + job.questions.map((q, i) => `${i + 1}. ${q.question}`).join('\n')
+ : 'Answer these common application questions:\n1. Why are you interested in this role?\n2. What is your relevant experience?\n3. What are your salary expectations?\n4. When can you start?\n5. Do you require visa sponsorship?';
+
+ P.qa = `You are a career coach.
+IMPORTANT: ALL answers MUST be in English. Be highly concise (1 sentence max for text inputs, Yes/No for radio inputs).
${prof}
JOB:
${ctx}
-Generate answers for ALL:
+${dynamicQuestions}
-## 1. Why are you interested in this role?
-[3-4 sentences specific to ${co} and this role — in English]
-
-## 2. Why ${co}?
-[2-3 sentences referencing something specific about the company]
-
-## 3. Relevant experience
-[4-5 sentences — most relevant achievements for this role]
-
-## 4. Expected salary
-[Competitive range for ${loc} market — USD and local currency]
-
-## 5. When can you start?
-Available immediately or within 2 weeks.
-
-## 6. Visa sponsorship needed?
-Based in Jordan. Open to relocation. Willing to process visa requirements.
-
-## 7. Notice period
-Available immediately — currently seeking new opportunities.
-
-## 8. Willing to relocate?
-Yes, open to ${loc} and broader Middle East.
-
-## 9. Why are you the best candidate?
-[3-4 sentences — unique differentiators for THIS role]
-
-## 10. Key technology experience
-[Identify top 2-3 technologies from the job description and write specific answers about my experience]
-
-RULES: ALL answers in English. Ready to paste. No brackets. Concise. Use numbers.`;
+RETURN EXACTLY A RAW JSON OBJECT where keys are the exact questions above and values are your concise answers.
+Do NOT use markdown code blocks like \`\`\`json. Just return the raw JSON.
+Example:
+{
+ "Have you completed the following level of education: Bachelor's Degree?": "Yes",
+ "How many years of work experience do you have with Infrastructure?": "6",
+ "Why are you interested in this role?": "My background in mapping perfectly aligns with your needs."
+}`;
P.benefits = `You are a career analyst specializing in tech compensation in MENA.
IMPORTANT: Respond ENTIRELY in English regardless of the job posting language.