def document_fn(fn: Callable, cls) -> tuple[str, list[dict], dict, str | None]:
    """
    Generates documentation for any function.
    Parameters:
        fn: Function to document
    Returns:
        description: General description of fn
        parameters: A list of dicts for each parameter, storing data for the parameter name, annotation and doc
        return: A dict storing data for the returned annotation and doc
        example: Code for an example use of the fn
    """
    doc_str = inspect.getdoc(fn) or ""
    doc_lines = doc_str.split("\n")
    signature = inspect.signature(fn)
    description, parameters, returns, examples = [], {}, [], []
    mode = "description"
    for line in doc_lines:
        line = line.rstrip()
        if line == "Parameters:":
            mode = "parameter"
        elif line.startswith("Example:"):
            mode = "example"
            if "(" in line and ")" in line:
                c = line.split("(")[1].split(")")[0]
                if c != cls.__name__:
                    mode = "ignore"
        elif line == "Returns:":
            mode = "return"
        else:
            if mode == "description":
                description.append(line if line.strip() else "<br>")
                continue
            if not (line.startswith("    ") or line.strip() == ""):
                print(line)
            if not (line.startswith("    ") or line.strip() == ""):
                raise SyntaxError(
                    f"Documentation format for {fn.__name__} has format error in line: {line}"
                )
            line = line[4:]
            if mode == "parameter":
                colon_index = line.index(": ")
                if colon_index < -1:
                    raise SyntaxError(
                        f"Documentation format for {fn.__name__} has format error in line: {line}"
                    )
                parameter = line[:colon_index]
                parameter_doc = line[colon_index + 2 :]
                parameters[parameter] = parameter_doc
            elif mode == "return":
                returns.append(line)
            elif mode == "example":
                examples.append(line)
    description_doc = " ".join(description)
    parameter_docs = []
    for param_name, param in signature.parameters.items():
        if param_name.startswith("_"):
            continue
        if param_name == "self":
            continue
        if param_name in ["kwargs", "args"] and param_name not in parameters:
            continue
        parameter_doc = {
            "name": param_name,
            "annotation": param.annotation,
            "doc": parameters.get(param_name),
        }
        if param_name in parameters:
            del parameters[param_name]
        if param.default != inspect.Parameter.empty:
            default = param.default
            if isinstance(default, str):
                default = '"' + default + '"'
            if default.__class__.__module__ != "builtins":
                default = f"{default.__class__.__name__}()"
            parameter_doc["default"] = default
        elif parameter_doc["doc"] is not None:
            if "kwargs" in parameter_doc["doc"]:
                parameter_doc["kwargs"] = True
            if "args" in parameter_doc["doc"]:
                parameter_doc["args"] = True
        parameter_docs.append(parameter_doc)
    if parameters:
        raise ValueError(
            f"Documentation format for {fn.__name__} documents "
            f"nonexistent parameters: {', '.join(parameters.keys())}. "
            f"Valid parameters: {', '.join(signature.parameters.keys())}"
        )
    if len(returns) == 0:
        return_docs = {}
    elif len(returns) == 1:
        return_docs = {"annotation": signature.return_annotation, "doc": returns[0]}
    else:
        return_docs = {}
        # raise ValueError("Does not support multiple returns yet.")
    examples_doc = "\n".join(examples) if len(examples) > 0 else None
    return description_doc, parameter_docs, return_docs, examples_doc

    Generates documentation for any function.
    Parameters:
        fn: Function to document
    Returns:
        description: General description of fn
        parameters: A list of dicts for each parameter, storing data for the parameter name, annotation and doc
        return: A dict storing data for the returned annotation and doc
        example: Code for an example use of the fn
    
client/python/gradio_client/documentation.py