
  * Copyright ( c ) Meta Platforms , Inc. and affiliates . 
  * 
  * This source code is licensed under the MIT license found in the 
  * LICENSE file in the root directory of this source tree . 
 
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *)


  * Process jsx text normalize via the following rules : 
  * - Each line of the JSXText is trimmed of whitespace 
  * - Empty or pure whitespace lines are removed 
  * - Tabs are replaces with spaces 
  * - The lines are joined together with spaces 
  * 
  * This is hard for two main reasons : 
  *   1 . We ca n't use  
  *   2 . It 's not enough to trim the text , we also need to figure out the line and 
  *      column for the start and end of the text 
 
 * Process jsx text normalize via the following rules:
 * - Each line of the JSXText is trimmed of whitespace
 * - Empty or pure whitespace lines are removed
 * - Tabs are replaces with spaces
 * - The lines are joined together with spaces
 *
 * This is hard for two main reasons:
 *  1. We can't use Str
 *  2. It's not enough to trim the text, we also need to figure out the line and
 *     column for the start and end of the text
 *)
let trim_jsx_text =
  (* Removes all the spaces from the beginning of the string *)
  let prefix_trim =
    let rec trimmer str len idx =
      if idx >= len then
        ""
      else if str.[idx] = ' ' then
        trimmer str len (idx + 1)
      else
        String.sub str idx (len - idx)
    in
    (fun str -> trimmer str (String.length str) 0)
  in
  (* Removes all the spaces from the end of the string *)
  let suffix_trim =
    let rec trimmer str idx =
      if idx < 0 then
        ""
      else if str.[idx] = ' ' then
        trimmer str (idx - 1)
      else
        String.sub str 0 (idx + 1)
    in
    (fun str -> trimmer str (String.length str - 1))
  in
  fun loc value ->
    (* Tabs get turned into spaces *)
    let value = String_utils.replace_char '\t' ' ' value in
    (* The algorithm is line based, so split the string into lines *)
    let lines = String_utils.split_into_lines value in
    let last_line = List.length lines - 1 in
    let trimmed_lines =
      Base.List.mapi
        ~f:(fun idx line ->
  Remove the leading whitespace from every line but the first
          let line =
            if idx <> 0 then
              prefix_trim line
            else
              line
          in
          (* Remove the trailing whitespace from every line but the last *)
          if idx <> last_line then
            suffix_trim line
          else
            line)
        lines
    in
  Figure out the first and last non - empty line , if there are any
    let (_, first_and_last_non_empty) =
      List.fold_left
        (fun (idx, first_and_last) line ->
          let first_and_last =
            if line <> "" then
              match first_and_last with
              | None -> Some (idx, idx)
              | Some (first, _) -> Some (first, idx)
            else
              first_and_last
          in
          (idx + 1, first_and_last))
        (0, None)
        trimmed_lines
    in
    match first_and_last_non_empty with
    | None -> None
    | Some (first_line, last_line) ->
      (* Filter out empty lines and turn newlines into spaces *)
      let trimmed = trimmed_lines |> List.filter (fun line -> line <> "") |> String.concat " " in
      Loc.(
        let start_line = loc.start.line + first_line in
        let end_line = loc.start.line + last_line in
  We want to know the column and offset for the first and last 
          * non - whitespace characters . We can do that by figuring out what those 
          * characters are and using String.index and String.rindex to search for 
          * them
         * non-whitespace characters. We can do that by figuring out what those
         * characters are and using String.index and String.rindex to search for
         * them *)
        let first_trimmed_line = List.nth trimmed_lines first_line in
        let last_trimmed_line = List.nth trimmed_lines last_line in
        let first_char = first_trimmed_line.[0] in
        let last_char = last_trimmed_line.[String.length last_trimmed_line - 1] in
        (* For column we just do a search within the line *)
        let start_column = String.index (List.nth lines first_line) first_char in
        let end_column = String.rindex (List.nth lines last_line) last_char + 1 in
  If we 're on the first line , then we need to see on which column the line 
            starts
           starts *)
        let start_column =
          if first_line = 0 then
            start_column + loc.start.column
          else
            start_column
        in
        let end_column =
          if last_line = 0 then
            end_column + loc.start.column
          else
            end_column
        in
        let loc =
          {
            loc with
            start = { line = start_line; column = start_column };
            _end = { line = end_line; column = end_column };
          }
        in
        Some (loc, trimmed)
      )

 Removes all the spaces from the beginning of the string 
 Removes all the spaces from the end of the string 
 Tabs get turned into spaces 
 The algorithm is line based, so split the string into lines 
 Remove the trailing whitespace from every line but the last 
 Filter out empty lines and turn newlines into spaces 
 For column we just do a search within the line 

  * Copyright ( c ) Meta Platforms , Inc. and affiliates . 
  * 
  * This source code is licensed under the MIT license found in the 
  * LICENSE file in the root directory of this source tree . 
 
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *)


  * Process jsx text normalize via the following rules : 
  * - Each line of the JSXText is trimmed of whitespace 
  * - Empty or pure whitespace lines are removed 
  * - Tabs are replaces with spaces 
  * - The lines are joined together with spaces 
  * 
  * This is hard for two main reasons : 
  *   1 . We ca n't use  
  *   2 . It 's not enough to trim the text , we also need to figure out the line and 
  *      column for the start and end of the text 
 
 * Process jsx text normalize via the following rules:
 * - Each line of the JSXText is trimmed of whitespace
 * - Empty or pure whitespace lines are removed
 * - Tabs are replaces with spaces
 * - The lines are joined together with spaces
 *
 * This is hard for two main reasons:
 *  1. We can't use Str
 *  2. It's not enough to trim the text, we also need to figure out the line and
 *     column for the start and end of the text
 *)
let trim_jsx_text =
  let prefix_trim =
    let rec trimmer str len idx =
      if idx >= len then
        ""
      else if str.[idx] = ' ' then
        trimmer str len (idx + 1)
      else
        String.sub str idx (len - idx)
    in
    (fun str -> trimmer str (String.length str) 0)
  in
  let suffix_trim =
    let rec trimmer str idx =
      if idx < 0 then
        ""
      else if str.[idx] = ' ' then
        trimmer str (idx - 1)
      else
        String.sub str 0 (idx + 1)
    in
    (fun str -> trimmer str (String.length str - 1))
  in
  fun loc value ->
    let value = String_utils.replace_char '\t' ' ' value in
    let lines = String_utils.split_into_lines value in
    let last_line = List.length lines - 1 in
    let trimmed_lines =
      Base.List.mapi
        ~f:(fun idx line ->
  Remove the leading whitespace from every line but the first
          let line =
            if idx <> 0 then
              prefix_trim line
            else
              line
          in
          if idx <> last_line then
            suffix_trim line
          else
            line)
        lines
    in
  Figure out the first and last non - empty line , if there are any
    let (_, first_and_last_non_empty) =
      List.fold_left
        (fun (idx, first_and_last) line ->
          let first_and_last =
            if line <> "" then
              match first_and_last with
              | None -> Some (idx, idx)
              | Some (first, _) -> Some (first, idx)
            else
              first_and_last
          in
          (idx + 1, first_and_last))
        (0, None)
        trimmed_lines
    in
    match first_and_last_non_empty with
    | None -> None
    | Some (first_line, last_line) ->
      let trimmed = trimmed_lines |> List.filter (fun line -> line <> "") |> String.concat " " in
      Loc.(
        let start_line = loc.start.line + first_line in
        let end_line = loc.start.line + last_line in
  We want to know the column and offset for the first and last 
          * non - whitespace characters . We can do that by figuring out what those 
          * characters are and using String.index and String.rindex to search for 
          * them
         * non-whitespace characters. We can do that by figuring out what those
         * characters are and using String.index and String.rindex to search for
         * them *)
        let first_trimmed_line = List.nth trimmed_lines first_line in
        let last_trimmed_line = List.nth trimmed_lines last_line in
        let first_char = first_trimmed_line.[0] in
        let last_char = last_trimmed_line.[String.length last_trimmed_line - 1] in
        let start_column = String.index (List.nth lines first_line) first_char in
        let end_column = String.rindex (List.nth lines last_line) last_char + 1 in
  If we 're on the first line , then we need to see on which column the line 
            starts
           starts *)
        let start_column =
          if first_line = 0 then
            start_column + loc.start.column
          else
            start_column
        in
        let end_column =
          if last_line = 0 then
            end_column + loc.start.column
          else
            end_column
        in
        let loc =
          {
            loc with
            start = { line = start_line; column = start_column };
            _end = { line = end_line; column = end_column };
          }
        in
        Some (loc, trimmed)
      )
