• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

JavaScript to Proofread Text in a Illustrator File

Participant ,
Jun 24, 2024 Jun 24, 2024

Copy link to clipboard

Copied

Hi Folks,

 

I'm working on a JavaScript to proofread my text in the Illustrator file. here's the scenario…

1) I have a Text file (.txt) that contains all the text.

2) I have Finished Illustrator file with layout, graphics, text (including and excluding the text from the Text file).

3) Currently, as a QC, my manual process is like this:

a) Copy the text (sentence by sentence or Paragraph by Paragraph) from the Text file and search it in the Illustrator file;

b) If a text is found, then move to the second Sentence or Paragraph and so on;

c) If a text is not found in the Illustrator file, then paste that Sentence or Paragraph in a new Text file, and repeat process 2, until all the text is processed.

 

I want to accomplish the same with a JavaScript, where the script will read the text from the Text file and find it in the ai file, if found, then move to the second sentence or para, if not found then copy the not-found text in a new Text file.

Here's the script I'm trying to accomplish but I'm not getting the right results. My sample ai and Text files are here.


Can you please help me finished my task and feel free to improvise it to make it better.

 

// Function to read a local text file selected by the user
function readTextFile(file) {
  var text = "";
  var rawFile = new File(file);
  rawFile.open("r");
  text = rawFile.read();
  rawFile.close();
  return text;
}

// Function to show the dialog for file selection
function showDialog() {
  var dialog = new Window("dialog", "Proof Reading…");
  dialog.alignChildren = "fill";
  dialog.alignChildren = "left";

  // Panel for Text file selection
  var textFilePanel = dialog.add("panel", undefined, "");
  textFilePanel.add("statictext", undefined, "Select the TEXT File:");
  textFilePanel.orientation = "row";
  var textFilePathInput = textFilePanel.add("edittext", undefined, "", {
    readonly: true
  });
  textFilePathInput.size = [302, 20];
  var textFileBrowseBtn = textFilePanel.add("button", undefined, "Browse");
  textFileBrowseBtn.onClick = function() {
    var file = File.openDialog("Select the text file", "*.txt", false);
    if (file) {
      textFilePathInput.text = file.fsName;
    }
  };

  // Dialog buttons
  var buttonGroup = dialog.add("group");
  buttonGroup.alignment = "center";
  buttonGroup.add("button", undefined, "OK", { name: "ok" });
  buttonGroup.add("button", undefined, "Cancel", { name: "cancel" });

  if (dialog.show() === 1) {
    // User clicked OK
    return {
      textFilePath: textFilePathInput.text
    };
  } else {
    return null; // User clicked Cancel or closed the dialog
  }
}

// Main function to search text in Illustrator
function searchAndVerifyText() {
  // Show the file selection dialog
  var filePaths = showDialog();
  if (filePaths === null) {
    alert("No file selected. Exiting script.");
    return;
  }

  // Read the selected text file
  var text = readTextFile(filePaths.textFilePath);
  var paragraphs = text.split(/\r?\n\s*\r?\n/); // Split paragraphs by blank lines

  // Check if there is an active Illustrator document
  if (app.documents.length == 0) {
    alert(
      "No open Illustrator document found. Please open a document and try again."
    );
    return;
  }

  var doc = app.activeDocument;

  // Create a new file for missing paragraphs
  var missingTextFilePath = filePaths.textFilePath.replace(
    ".txt",
    "_missing.txt"
  );
  var missingTextFile = new File(missingTextFilePath);
  missingTextFile.open("w");

  // Loop through each paragraph and search in Illustrator
  for (var i = 0; i < paragraphs.length; i++) {
    var paragraph = paragraphs[i];

    // Ensure the paragraph is a string and trim it
    if (typeof paragraph !== "string") {
      paragraph = String(paragraph);
    }

    // Debugging output
    $.writeln("Processing paragraph " + i + ": " + paragraph);

    try {
      paragraph = paragraph.trim();
    } catch (e) {
      $.writeln("Error trimming paragraph " + i + ": " + e.message);
      continue; // Skip this paragraph if there's an error
    }

    if (paragraph === "") {
      $.writeln("Paragraph " + i + " is empty, skipping.");
      continue; // Skip empty lines
    }

    var found = false;
    for (var j = 0; j < doc.textFrames.length; j++) {
      var textFrame = doc.textFrames[j];
      var textContent = textFrame.contents;

      // Debugging output
      $.writeln("Checking text frame " + j + " content: " + textContent);

      if (textContent.indexOf(paragraph) !== -1) {
        found = true;
        $.writeln("Paragraph found in text frame " + j + ": " + paragraph);
        break;
      }
    }

    if (!found) {
      $.writeln("Paragraph not found: " + paragraph);
      missingTextFile.writeln(paragraph); // Write the missing paragraph to the new file
    }
  }

  missingTextFile.close();

  // Display the result
  alert("Missing paragraphs saved in: " + missingTextFilePath);
}

// Run the verification
searchAndVerifyText();

 

 

 

 

TOPICS
Scripting

Views

292

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Engaged ,
Jun 25, 2024 Jun 25, 2024

Copy link to clipboard

Copied

Code looks like generative AI garbage. A complete waste of time trying to understand it. Honestly, you should just say if you don’t know how to write a script yourself and ask if someone here is willing to write it for you (free or paid).

 

As it happens, I just had a someone asking a very similar question so figured I’d see how long it takes to write a script in practice. (Answer: this is as much as I’m prepared to do as a freebie, but at least it points you in the right direction.)

 

function readTextFile(f) {
	f.encoding = 'UTF-8'; // presumably
	f.open('r');
	var result = f.read();
	f.close();
	return result;
}

function appendTextFile(f, s) {
	f.encoding = 'UTF-8'; // presumably
	f.open('a');
	f.writeln(s);
	f.close();
}


var doc = app.activeDocument;
var f = doc.fullName;
if (!f.exists) { throw new Error("Please save document and run again."); }

var originalTextFile = File.openDialog("Choose the original text file.");
var originalText = readTextFile(originalTextFile);
var originalParagraphs = originalText.replace(/\s*[\r\n]\s*/g, '\n').split(/\n/g);
originalParagraphs.sort();


var foundParagraphs = [];
for (var i = 0; i < doc.stories.length; i++) {
	var paragraphs = doc.stories[i].paragraphs;
	for (var j = 0; j < paragraphs.length; j++) {
		foundParagraphs.push(paragraphs[j].contents.replace(/^\s+|\s+$/g));
	}
}
foundParagraphs.sort();

// _matched.txt = text that is found in both documents
// _missing.txt = text that is in original text file but not in artwork
// _unknown.txt = text that is in artwork but not in original text file
var matchedFile = new File(originalTextFile.fullName.replace(/\.[^.]+$/, '_matched.txt'));
var missingFile = new File(originalTextFile.fullName.replace(/\.[^.]+$/, '_missing.txt'));
var unknownFile = new File(originalTextFile.fullName.replace(/\.[^.]+$/, '_unknown.txt'));
matchedFile.remove();
missingFile.remove();
unknownFile.remove();


for (var i = 0; i < originalParagraphs.length; i++) {
  var originalParagraph = originalParagraphs[i];
  while (foundParagraphs.length > 0 && foundParagraphs[0] < originalParagraph) {
    appendTextFile(unknownFile, foundParagraphs.shift());
  }
  if (foundParagraphs[0] === originalParagraph) {
    appendTextFile(matchedFile, foundParagraphs.shift());
  } else {
    appendTextFile(missingFile, originalParagraph);
  }
}

while (foundParagraphs.length > 0) {
  appendTextFile(unknownFile, foundParagraphs.shift());
}

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jun 28, 2024 Jun 28, 2024

Copy link to clipboard

Copied

Hi,

you're right, the code was modified using AI, but the results were not satisfactory.

 

Thanks for sparing your time and sharing the code with me, your code is much closer to what I was looking. It worked perfectly on the sample files. However, when I applied it on the actual files, then I'm getting error.

 

Actually, the source and final files are both in Adobe Illustrator (see here). I was just trying to create a script to read the text from the Text file. Where, I copied the data from the source Illustrator file to a text file.

It seems proofing the content between TXT and AI is not very efficient, so I think if a script can be created to proofread the content between ai files would be much efficient. In the shared files, the source copy is in the 'WM076305-12_SourceIllustrator.ai' file where the final artowrk is 'WM076305-12_FinalArtwork.ai'. Can you please help me with the script to read the text from the Source file and find it in the Final file and report any missing copy in a 'missing.txt' file.

Thanks,

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jun 28, 2024 Jun 28, 2024

Copy link to clipboard

Copied

LATEST

The script error looks like Illustrator being a buggy jerk: e.g. `paragraphs.length` reporting 3 paragraphs when there are only 2. You can work around it like this:

 

 

var foundParagraphs = [];
for (var i = 0; i < doc.stories.length; i++) {
	var paragraphs = doc.stories[i].paragraphs;
	for (var j = 0; j < paragraphs.length; j++) {
    try {
      foundParagraphs.push(paragraphs[j].contents.replace(/^\s+|\s+$/g));
		} catch (e) { // bug workaround where paragraphs.length reports e.g. 3 items but there are only 2
		  if (e.number !== 1302) { throw e; }
		}
	}
}
foundParagraphs.sort();

 

 

I have to say, testing with the supplied files (which you should really anonymize before sharing, btw) the results are disappointing. That’s not really surprising to me: I was prototyping this sort of QA/revision autonomation over a decade ago and it is never as straightforward as it sounds. Pack copy documents rarely match exactly what appears on the artwork, e.g. “en_GB • Jute roller blind” ends up as “Jute roller blind”, and some fields don’t appear as text at all (e.g. picto names like “Wash care symbol - professional cleaning_do not dry clean.pdf”).

 

BTW, the SourceIllustrator file is not an improvement over the plain text file (which itself is not great), so I wouldn’t bother with that. If you can get the original pack copy document in XML or other structured format, that’s a better starting point as that tells you what each piece of text actually means. From there, you can selectively clean each one according to the same rules the artist follows, e.g. removing the “en_GB/fr_FR/etc •” crud, before trying to match it in the artwork.

 

I must emphasize: your entire ability to automate anything hangs on the quality of your inputs. If the customer’s pack copy is a sloppy mess that only a human artworker/QAer can reliably interpret, don’t even try. Maybe when AGI gets good enough, you’ll be able to throw unpredictable data at it and it’ll do as good a job as a human at making sense of it, but classical automation demands strictly defined, absolutely consistent inputs or you only dig yourself an even bigger hole.

 

The part of my script which extracts the artwork text would be improved by having it ignore the non-pack copy text on “cutter” and “legend” layers. My implementation (which was really just proof of concept) gets the document’s stories, ’cos that’s simplest, but it should really iterate through the individual text frames on the “artwork” layer to extract their text. Oh, and it should also check for any text box overflows while it’s doing that, as an obvious QA issue. (This still won’t guarantee the text is visible on pack, e.g. a text frame could be hidden under an image or solid fill instead of on top of it, but it’d be a very badly built artwork that did that. For that level of verification, you’ll need an OCR approach—which has its own challenges.)

 

Beyond that, for the text comparison step, you really want to use fuzzy text matching, e.g. fuse.js. This will identify text which is mostly, but not quite, identical. Touch-wood that should match up most of the pack copy fields to the text that appears in the artwork, at which point the fine differences (which might just be extra whitespace or fixed punctuation) can be highlighted for manual review. Find yourself a Node.js developer if you can’t write that script yourself. Interop between ExtendScript and Node scripts is a chore (for sharing data between them it’s easiest to read and write JSON files).

 

 

TBH, it’d be better to autonomate first artwork production, using scripts to place all the pack copy into a tear-off sheet of pre-built text frames/panels which the artworker can drop into place, or take a lead artwork and replace its original text to assist in producing the adaptations. Eliminating manual copy-paste will reduce QA as the text is already correctly formatted within Illustrator and most text frames be dropped straight into the artwork and sized and positioned to fit. Prebuilt text frames/panels can also be tagged so that QA scripts can easily locate them and compare them for changes. It is much easier to automate checking/amending an artwork that was partly/fully created by automation than an artwork built completely manually. Some human interaction will be unavoidable with artworks of this complexity and range, but you can reduce the variability that human operators always introduce.

 

Sorry that’s not an easy answer, but it’s not an easy problem, both technological and logistical. (I was 90% automating those artworks over a decade ago and the industry still hasn’t progressed any. And while I had first artworks solved I still hadn’t figured a satisfactory solution to QA and amends by the time I left, so I can’t give you all the answers as I don’t know them myself.)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines